REpresentational State Transfer (REST) is a style of software architecture for distributed systems such as the World Wide Web.
A RESTful API is a web service implemented using HTTP and the principles of REST.
Roy Fielding doctoral dissertation, 2000.
Separate clients and servers.
Each request from the client contains all the information necessary to service the request.
Clients can cache responses, if permitted by the server.
Load balancers, proxies, firewalls etc.
Client can request code from server and execute it.
Between the client and the server.
Through URI. api.toshl.com/users/42
POST, GET, PUT/PATCH, DELETE
Through meta data.
HATEOAS, huh?
A client interacts with a network application entirely through hypermedia provided dynamically by application servers. A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia.
In HTML <a>
, <form>
, <img>
etc.
Think things through
Check the spec RFC 2616.
https://api.toshl.com/expenses
https://api.toshl.com/expenses/42
https://api.toshl.com/budgets
https://api.toshl.com/export
$ curl -v https://api.toshl.com
> GET / HTTP/1.1
>
< HTTP/1.1 204 No Content
< Allow: GET
< Link: </expenses>; rel="expenses",</expenses/tags>; rel="expense tags",</incomes>; rel="incomes",...
< Content-Length: 0
< Content-Type: application/json
Include a handy Link
header.
$ curl -v https://api.toshl.com/expenses
> GET / HTTP/1.1
>
< HTTP/1.1 200 OK
< Allow: GET, POST, HEAD
$ curl -v -X POST -d "..." https://api.toshl.com/expenses
> POST /expenses HTTP/1.1
>
< HTTP/1.1 201 Created
< Allow: GET,POST
< Location: /expenses/1031
< Content-Length: 176
< Content-Type: application/json
<
{"id":1031,"amount":100,"currency":"EUR","rate":1,"date":"2012-10-23","desc":null,"tags":["food"],"loc":["0.000000","0.000000"],"modified":"2012-10-23T19:20:46+00:00Z","repeat":null,"extra":null}
Spot the error?
$ curl -v -X POST -d "..." https://api.toshl.com/expenses
> POST /expenses HTTP/1.1
>
< HTTP/1.1 201 Created
< Allow: GET,POST
< Location: /expenses/1031
< Content-Length: 200
< Content-Type: application/json
<
{"id":1031,"href":"/expenses/1031","amount":100,"currency":"EUR","rate":1,"date":"2012-10-23","desc":null,"tags":["food"],"loc":["0.000000","0.000000"],"modified":"2012-10-23T19:20:46+00:00Z","repeat":null,"extra":null}
HATEOAS - include a link to the resource URI.
$ curl -v https://api.toshl.com/expenses/1031
> GET /expenses/1031 HTTP/1.1
>
< HTTP/1.1 200 OK
< Allow: GET,PUT,PATCH,DELETE
< Content-Length: 219
< Content-Type: application/json
<
{"id":1031,"href":"/expenses/1031","amount":100,"currency":"EUR","rate":1,"date":"2012-10-23","desc":null,"tags":["food"],"loc":["0.000000","0.000000"],"modified":"2012-10-23T19:20:46+00:00Z","repeat":null,"extra":null}
$ curl -v -X PUT -d "..." https://api.toshl.com/expenses/1031
> PUT /expenses/1031 HTTP/1.1
>
< HTTP/1.1 200 OK
< Allow: GET,PUT,PATCH,DELETE
< Content-Length: 219
< Content-Type: application/json
<
{"id":1031,"href":"/expenses/1031","amount":200,"currency":"EUR","rate":1,"date":"2012-10-23","desc":null,"tags":["food"],"loc":["0.000000","0.000000"],"modified":"2012-10-23T19:20:46+00:00Z","repeat":null,"extra":null}
GET and PUT are idempotent methods.
$ curl -v -X DELETE https://api.toshl.com/expenses/1031
> DELETE /expenses/1031 HTTP/1.1
>
< HTTP/1.1 204 No Content
< Allow: GET,PUT,PATCH,DELETE
< Content-Length: 0
< Content-Type: application/json
<
{
"id": "income_limit"
"description": "Income limit reached."
}
application/json
application/vnd.toshl+json
application/vnd.toshl.expense+json
URI
https://api.toshl.com/v1/expenses/
Media Types
application/vnd.toshl.v1+json
application/vnd.toshl.expense.v1+json
https://api.toshl.com/expenses?page=1&per_page=20
What about previous/next/last links?
$ curl -v https://api.toshl.com/expenses
> GET / HTTP/1.1
>
< HTTP/1.1 200 OK
< Allow: GET, POST
< Link: <expenses?page=2>; rel="next",<expenses?page=9>; rel="last"
Timestamp 2012-10-23T22:05:37+00:00Z
. ISO 8601.
Add ?since=1351033818
Add ?since_id=37821
Using Last-Modified
and If-Modified-Since
Using Last-Modified
and ?since=2012-10-23T22:05:37+00:00Z
ETag: "3e12ec4d-994fefe4-24c8868"
If-None-Match: "3e12ec4d-994fefe4-24c8868"
OAuth 2.0
GET /expenses HTTP/1.1
Host: api.toshl.com
Authorization: Bearer vF9dft4qmT
OAuth 2.0 + MAC
GET /expenses HTTP/1.1
Host: api.toshl.com
Authorization: MAC id="h480djs93hd8",
nonce="264095:dj83hs9s",
mac="SLDJd4mg43cjQfElUs3Qub4L6xE="
A client interacts with a network application entirely through hypermedia provided dynamically by application servers. A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia.
The WWW is fundamentally a distributed hypermedia application. —Richard Taylor
APIs and clients, they are hiding in plain sight.
Websites, HTML and the browser.
GET page
.GET uri
request.POST uri "data"
request.Web Resource Modeling Language
WRML, pronounced like "Wormle", is an open source project focused on providing standards, frameworks, and tools that support the development of web-oriented, client-server applications.
> GET /common/Collection HTTP/1.1 Host: api.schemas.wrml.org
< HTTP/1.1 200 OK
< Content-Type: application/wrml;
< format="http://api.formats.wrml.org/application/json"; schema="http://api.schemas.wrml.org/common/Collection"
{"name" : "Collection", ...}
// sample collection object
{
"collection" : {
"version" : "1.0",
"href" : URI,
"links" : [ARRAY],
"items : [ARRAY],
"queries" : [ARRAY],
"template" : {OBJECT},
"error" : {OBJECT}
}
}