Beruflich Dokumente
Kultur Dokumente
(@fvioz)
Good ways to
build an api
Agenda
Know the standards
Design human readable URLs
JSON as beautiful object
Thinking big
Methods
GET means retrieve whatever information
POST used to request that the origin server accept the entity enclosed in
the request as a new subordinate of the resource
PUT requests that the enclosed entity be stored under the supplied
Request-URI
DELETE requests that the origin server delete the resource identified by
the Request-URI
HEAD method is identical to GET except that the server MUST NOT return
a message-body in the response
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
https://github.com/3scale/httpstatus_cocktails/
Success codes
200 OK - Response to a successful GET, PUT, PATCH or DELETE.
Can also be used for a POST that doesn't result in a creation.
201 Created - Response to a POST that results in a creation.
Should be combined with a Location header pointing to the
location of the new resource
204 No Content - Response to a successful request that won't
be returning a body (like a DELETE request)
304 Not Modified - Used when HTTP caching headers are in
play
Error codes
400 Bad Request - The request is malformed, such as if the body does
not parse
401 Unauthorized - When no or invalid authentication details are
provided. Also useful to trigger an auth popup if the API is used from a
browser
403 Forbidden - When authentication succeeded but authenticated
user doesn't have access to the resource
404 Not Found - When a non-existent resource is requested
405 Method Not Allowed - When an HTTP method is being requested
that isn't allowed for the authenticated user
Error codes
410 Gone - Indicates that the resource at this end point is no
longer available. Useful as a blanket response for old API versions
415 Unsupported Media Type - If incorrect content type was
provided as part of the request
422 Unprocessable Entity - Used for validation errors
429 Too Many Requests - When a request is rejected due to rate
limiting
500 Internal Server Error
JSON
JSON
Definitions
Resource: A single instance of an object. For example, an animal.
Collection: A collection of homogeneous objects. For example, animals.
Consumer: A client computer application capable of making HTTP
requests.
Third Party Developer: A developer not a part of your project but who
wishes to consume your data.
Endpoint: An API URL on a Server which represents either a Resource or
an entire Collection.
URL Segment: A slash-separated piece of information in the URL.
Choose a root
Endpoints
Collections
https://api.example.com/v1/friends
https://api.example.com/v1/employees
Use nouns but no verbs
Use plural nouns
Endpoints
Resource
GET
POST
GET
PUT
PATCH
Filtering
Minimize the arbitrary limits imposed on Third Party Developers
Filtering
?limit=10: Reduce the number of results returned to the
Consumer (for Pagination)
?offset=10: Send sets of information to the Consumer (for
Pagination)
?sort=+name,-age: Sort the results based on the specified
attribute (ORDER BY name ASC, ORDER BY age DESC)
?fields=name,age,friends: Select the attributes for a results
(SELECT name, age)
/comments?filter[post]=1,2&filter[author]=12
Deep level
Use sub-resources for relations
Simplify associations - sweep complexity under the ?
GET /companies/1/departments/1/
employes/1
GET /companies/1
GET /companies/1/departments
GET /departments/1/employees
GET /dogs/color/red/state/running/
location/park
GET /employees/1
GET /dogs?color=red&state=running&location=park
{
"data": {
},
"errors": {
},
"meta": {
// non-standard meta-information about the primary data.
},
"included": {
// a list of resource objects that are related to the primary data and/or
// each other ("included resources").
}
}
Resource structure
GET
/articles/1
{
data: {
"type": "articles",
"id": "1",
"title": "Rails is Omakase",
"links": {
"self": "https://api.example.com/articles/1"
"comments":"https://api.example.com/articles/1/comments"
}
}
}
Collection structure
GET
"data": [{
"type": "articles",
"id": "1",
"title": "JSON API paints my bikeshed!",
"links": {
"self": https://api.example.com/articles/1",
"authors": {
"self": https://api.example.com/articles/1/authors,
"linkage": { "type": "people", "id": "9" }
},
"comments": {
"self": https://api.example.com/articles/1/comments"
}
}
}],
/articles
"included": [{
"type": "people",
"id": "9",
"first-name": "Dan",
"last-name": "Gebhardt",
"links": {
"self": https://api.example.com/people/9"
}
}]
Meta structure
GET
/articles/1
{
"meta": {
"copyright": "Copyright 2015 Example Corp.",
"authors": [
"Yehuda Katz",
"Steve Klabnik",
"Dan Gebhardt"
]
}
}
Pagination
GET
{
"meta": {
"count": 5,
"pagination":
first: 1,
last: 5,
"prev": 1,
"next":
"current":
"per_page":
"count":
}
}
3,
2,
5,
23
/articles
Errors
POST
/articles
{
"errors": {
"code": 422,
"status": "Invalid Resource",
"title": "The current resource was deemed invalid.",
"messages": {
"name":
["can't be blank"],
id_number: ["can't be blank", "is not a number"],
"company":
["is too short (minimum is 5 characters)", "is invalid"]
}
}
}
k
n
i
h
T
g
in
g
i
b
Versioning
1. URL: You simply whack the API version into the URL, for
example: https://api.example/v2/accounts/foo
2. Custom request header: You use the same URL as before
but add a header, for example: https://api.example.com/
accounts/foo
api-version: 2
3. Accept header: You modify the accept header to specify the
version, for example: https://api.example.com/accounts/foo
Accept: application/vnd.api.v2+json
Request Headers
Caching
There are 2 approaches: ETag and Last-Modified
ETag: When generating a request, include a HTTP header ETag
containing a hash or checksum of the representation. This value should
change whenever the output representation changes. Now, if an inbound
HTTP requests contains a If-None-Match header with a matching ETag
value, the API should return a 304 Not Modified status code instead of
the output representation of the resource.
Last-Modified: This basically works like to ETag, except that it uses
timestamps. The response header Last-Modified contains a timestamp in
RFC 1123 format which is validated against If-Modified-Since. Note that
the HTTP spec has had 3 different acceptable date formats and the server
should be prepared to accept any one of them.
Rate limiting
X-Rate-Limit-Limit - The number of allowed requests in
the current period
X-Rate-Limit-Remaining - The number of remaining
requests in the current period
X-Rate-Limit-Reset - The number of seconds left in the
current period
Resources
http://json.org
http://jsonapi.org
http://apiux.com
http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-whichis.html
http://www.toptal.com/api-developers/5-golden-rules-for-designing-agreat-web-api
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Questions ?
,
s
k
n
a
h
e
T
n
o
y
r
e
v
E