{"links":[ {"rel":"author", "uri":"http://javier-ramirez.com"}, {"rel":"work", "uri":"http://aspgems.com"}, {"rel":"blog", "uri":"http://formatinternet.com"}, {"rel":"twittEr", "uri":"http//twitter.com/supercoco9"}]}
usable REST APIs
1996
1995
1996
1994
2001
1999
2004
Web usability is an approach to make web sites
easy to use for an end-user, without the requirement that any specialized training be
undertaken.[]
LearnabilityEfficIeNcyMemorabiliTyErrorsSatisfActiOn
I want YOUto make
a (REST) API
REST in a nutshell
client server stateless layered and cacheable
Resources
Resource Identifiers
Resource metadata
Uniform interface
operations
Representations
Representation metadata
Optionally: code on demand
easy
making a REST API
with Rails?
BASIC
WEB/api
functionality
IN RAILS
Cohesion
pleasE
separation of concerns
SUCCESS consistently
fail consistently
expose ONLY
WHAT ISStrictly
necessary
resources are not models
Aggregation/
composition
Multiple
representations
Multiple consumers
All your
FORMAT
are belong
to us
> curl -d "[email protected]&password=keepdreaming" https://invoicefu.com/api/session?format=json
{"user":{"id":108,"name":"Nicolas Carroll","email":"[email protected]","locale":"en","twitter_nickname":null,"facebook_uid":null,"facebook_nickname":null,"api_key":"dbd349b30b6d9fde97b01b827e6be5ed1e4fbe72","links":[{"rel":"session","uri":"https://invoicefu.com/api/session","methods":"GET,POST,DESTROY"},"rel":"account","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake","methods":"GET,PUT"},"rel":"clients","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/clients","methods":"GET,POST"},{"rel":"new_client","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/clients/new","methods":"GET"},{"rel":"invoices","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices","methods":"GET,POST"},{"rel":"new_invoice","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices/new","methods":"GET"},{"rel":"proformas","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/proformas","methods":"GET,POST"},{"rel":"new_proforma","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/proformas/new","methods":"GET"}]}}
> curl -d "[email protected]&password=yeahyeah" "https://invoicefu.com/api/session?&format=xml
<?xml version="1.0" encoding="UTF-8"?><user> <id>108</id> <name>Nicolas Carroll</name> <email>[email protected]</email> <locale>en</locale> <twitter-nickname nil="true"></twitter-nickname> <facebook-uid nil="true"></facebook-uid> <facebook-nickname nil="true"></facebook-nickname> <api-key>dbd349b30b6d9fde97b01b827e6be5ed1e4fbe72</api-key> <links> <link> <rel>session</rel> <uri>https://invoicefu-localhost.com/api/session</uri> <methods>GET,POST,DESTROY</methods> </link> <link> <rel>account</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake</uri> <methods>GET,PUT</methods> </link> <link> <rel>clients</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/clients</uri> <methods>GET,POST</methods> </link> <link> <rel>new_client</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/clients/new</uri> <methods>GET</methods> </link> (…)
</links></user>
can I haz cat readable anzwa
THE
ACCEPT
HEADER
HTTP/REST StandardUnambiguousResources != RepresentationsVersion as you need it
Not everyone supports headers or custom types
Less obviousHarder to useNon standard content-typesSkips HTTP server logs
Accept: application/vnd.aspgems.invoicefu.v1.xml
templates
for new
resources> curl "https://invoicefu.com/api/v1/accounts/108-cole-mertz-fake/invoices/new?api_key=ddd349b30b6d9fde97b01b827e6be5ed1e4fbe72&format=json"
{"invoice":{"number":"2011/30","issued_on":"2011-12-12","proforma_id":null,"notes":null,"footer":null,"locale":"en","currency_code":"USD","currency_symbol":"$","ac_name":"Cole-Mertz#FAKE","ac_company_number_name":"Company number","ac_company_number":"25465828K","ac_tax_number_name":"VAT Number","ac_tax_number":"ES25464828k","ac_address":"234 brecknock road","ac_city":"london","ac_province":null,"ac_postal_code":"n18 5bq","ac_country_name":"United Kingdom","cl_email":null,"cl_name":null,"cl_company_number_name":null,"cl_company_number":null,"cl_tax_number_name":null,"cl_tax_number":null,"cl_address":null,"cl_city":null,"cl_province":null,"cl_postal_code":null,"cl_country_name":null,"invoice_lines":[],"discount_percent":null,"tax_lines":[{"name":"TVA","signed_percent":"19.6"}],"paid":"0.0","links":[{"rel":"payments","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices//payments","methods":"POST"},{"rel":"account","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake","methods":"GET,PUT"},{"rel":"client","uri":null,"methods":"GET,PUT,DELETE"},{"rel":"proforma","uri":null,"methods":"GET,PUT,DELETE"},{"rel":"pdf","uri":null,"methods":"GET"},{"rel":"invoices","uri":"https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices","methods":"GET,POST"}]}}j
EASy
To
FIND
> curl https://invoicefu.com?format=xml (or curl -H "Accept: application/xml" "https://invoicefu.com")
<?xml version="1.0" encoding="UTF-8"?><invoicefu> <links> <link> <rel>session</rel> <uri>https://invoicefu.com/api/session</uri> <methods>POST.DELETE</methods> </link> <link> <rel>countries</rel> <uri>https://invoicefu.com/api/countries</uri> <methods>GET</methods> </link> <link> <rel>api_v1</rel> <uri>https://invoicefu.com/api/session?api_version=1</uri> <methods>POST.DELETE</methods> </link> <link> <rel>xml_representation</rel> <uri>https://invoicefu.com/api/session?format=xml</uri> <methods>POST.DELETE</methods> </link> <link> <rel>json_representation</rel> <uri>https://invoicefu.com/api/session?format=json</uri> <methods>POST.DELETE</methods> </link> <link> <rel>strict_parameters</rel> <uri>https://invoicefu.com/api/session?strict=true</uri> <methods>POST.DELETE</methods> </link> </links></invoicefu>
> curl -d "[email protected]&password=yeahyeah" "https://invoicefu.com/api/session?&format=xml
<?xml version="1.0" encoding="UTF-8"?><user> <id>108</id> <name>Nicolas Carroll</name> <email>[email protected]</email> <locale>en</locale> <twitter-nickname nil="true"></twitter-nickname> <facebook-uid nil="true"></facebook-uid> <facebook-nickname nil="true"></facebook-nickname> <api-key>dbd349b30b6d9fde97b01b827e6be5ed1e4fbe72</api-key> <links> <link> <rel>session</rel> <uri>https://invoicefu-localhost.com/api/session</uri> <methods>GET,POST,DESTROY</methods> </link> <link> <rel>account</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake</uri> <methods>GET,PUT</methods> </link> <link> <rel>clients</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/clients</uri> <methods>GET,POST</methods> </link> <link> <rel>new_client</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/clients/new</uri> <methods>GET</methods> </link> <link> <rel>invoices</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/invoices</uri> <methods>GET,POST</methods> </link>
(…)
</links></user>
BASIC ACCESS AUTHENTICATION
OAUTH
TOKEN
authenticate_or_request_with_http_basic do |login, password| User.find_by_login_and_password login, password endUser and password must be passed every time
Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join ) User.find_by_login_and_api_key( params[:login], params[:api_key] ) Client can send it as a parameter or as a header
Depends on third party libraries Requires initial registration of client and more integration
Performance
params &
debug
> curl "https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices/new?api_key=ddd349b30b6d9fde97b01b827e6be5ed1e4fbe72&format=xml&debug=1"
<?xml version="1.0" encoding="UTF-8"?><errors> <error>extra params found: debug. Allowed params are: account_id,client_id,invoice_id,proforma_id</error></errors>
> curl "https://invoicefu.com/api/accounts/108-cole-mertz-fake/invoices/new?api_key=ddd349b30b6d9fde97b01b827e6be5ed1e4fbe72&format=xml&debug=1&strict=false"<?xml version="1.0" encoding="UTF-8"?><invoice> <number>2011/30</number> <issued-on>2011-12-11</issued-on> <proforma-id nil="true"></proforma-id> (...) <links> (...) <link> <rel>invoices</rel> <uri>https://invoicefu-localhost.com/api/accounts/108-cole-mertz-fake/invoices</uri> <methods>GET,POST</methods> </link> </links></invoice>
WADLjson schema
helping
your users
{ "name":"Product", "properties":{ "id":{ "type":"number", "description":"Product identifier", "required":true }, "name":{ "description":"Name of the product", "type":"string", "required":true }, "price":{ "required":true, "type": "number", "minimum":0, "required":true }, "tags":{ "type":"array", "items":{ "type":"string" } } }, "links":[ { "rel":"full", "href":"{id}" }, { "rel":"comments", "href":"comments/?id={id}" } ] }
<?xml version="1.0"?> <application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://wadl.dev.java.net/2009/02 wadl.xsd" xmlns:tns="urn:yahoo:yn" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:yn="urn:yahoo:yn" xmlns:ya="urn:yahoo:api" xmlns="http://wadl.dev.java.net/2009/02"> <grammars> <include href="NewsSearchResponse.xsd"/> <include href="Error.xsd"/> </grammars> <resources base="http://api.search.yahoo.com/NewsSearchService/V1/"> <resource path="newsSearch"> <method name="GET" id="search"> <request> <param name="appid" type="xsd:string" style="query" required="true"/> 22 <param name="type" style="query" default="all"> <option value="all"/> <option value="any"/> <option value="phrase"/> </param> <param name="start" style="query" type="xsd:int" default="1"/> <param name="language" style="query" type="xsd:string"/> </request> <response status="200"> <representation mediaType="application/xml" element="yn:ResultSet"/> </response> <response status="400"> <representation mediaType="application/xml" element="ya:Error"/> </response> </method> </resource> </resources> </application>
tools
curl
Hurl
Httparty
restclient
apigee
Top Related