TL;DR of https://pages.apigee.com/rs/351-WXY-166/images/ebook-2013-03-wad.pdf
[EDIT 04/01/2021] https://docs.apigee.com/files/Web-design-the-missing-link-ebook-2016-11.pdf
- Nouns are good; verbs are bad
- keep simple things simple
- keep your base URL simple and intuitive
- 2 base URLs per resource
/dogsfor collections;/dogs/1234for itemPOST /dogscreate a new dogGET /dogslist dogsPUT /dogsbulk update dogsDELETE /dogsdelete all dogsPOST /dogs/1234ErrorGET /dogsShow BoPUT /dogsIf exists update Bo; else ErrorDELETE /dogsdelete Bo- use plural nouns
- be consistent
- concrete names are better than abstract
- simplify associations
GET /owners/5678/dogsget all dogs belonging to specific ownerPOST /owners/5678/dogsto create a new dog for that owner- you should not need deeper URL than
/resource/identifier/resource
- sweep complexity behind the '?'
GET /dogs?color=red&state=running&location=parkget all red dogs running in the park
- handling errors is very important piece of the puzzle
- test-first and tdd -> learn to write code through errors
- use HTTP status code, but the common ones
- 200 - OK
- 400 - Bad Request
- 500 - Internal Server Error
- then make messages in the payload as verbose as possible
- add a link in description to more information about the error
- never release an API without a version
- make the version mandatory
- a 'v' prefix on the left in the URL:
/v1/dogs - use a simple ordinal number (v1, v2, ...)
- in the URL: if it changes the logic you write to handle the response
- in the header: if it does not change the logic for each response, like OAuth information
- these for example, all represent the same resource
/dogs/1 Content-Type: application/json/dogs/1 Content-Type: application/xml/dogs/1 Content-Type: application/png- but the code to handle the responses would be very different
- there is no question the header is more correct and it is still a very strong API design
/dogs?fields=name,color,locationreturns only needed fields for developer/dogs?limit=25&offset=50returns the 25 rows starting at 50s row
- user verbs not nouns:
/convert?from=EUR&to=CNY&amount=100
- Google Data:
?alt=json - Foursquare:
venue.json - Digg:
Accept: application/jsonor?type=json - recommandation:
/dogs/1234.json - use json as default format
var myObject = JSON.parse(response); var timing = myObject.createdAt;- json/javascript conventions
- use resourcefull API:
/dogs?q=red+running+park - multiple resources:
/search?q=fluffy+fur - return specific format:
/search.json?q=fluffy+furor/search.xml?q=fluffy+fur
- assuming your top-level domain is
teachdogrest.com - API gateway should be:
api.teachdogrest.com - the developer portal should be
developers.techdogrest.com - redirect is your friend:
- api -> developers (if from browser)
- dev -> developers
- developer -> developers
- use OAuth - OAuth 2.0
- Create a brown dog named Al
POST /dogs
name=Al&furColor=brown
// Response
200 OK
{
"dog": {
"id": "1234",
"name": "Al",
"furColor": "brown"
}
}
- Rename Al to Rover - Update
PUT /dogs/1234
name=Rover
// Response
200 OK
{
"dog": {
"id": "1234",
"name": "Rover",
"furColor": "brown"
}
}
- Tell me about a particular dog
GET /dogs/1234
// Response
200 OK
{
"dog": {
"id": "1234",
"name": "Rover",
"furColor": "brown"
}
}
- Tell me about all the dogs
GET /dogs
// Response
200 OK
{
"dogs":
[{"dog": {
"id": "1233",
"name": "Fido",
"furColor": "white"}},
{"dog": {
"id": "1234",
"name": "Rover",
"furColor": "brown"}}...],
"_metadata":
[{"totalCount": 327, "limit": 25, "offset": 100}]
Delete Rover :-(
DELETE /dogs/1234
// Response
200 OK
Read more: https://blog.apigee.com/taglist/restful
- Your product manager is a key member of your API team
- "Use the façade pattern when you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve."
- How-to:
- Design the ideal API. The API design should be self-consistent.
- Implement the design with data stubs.
- Mediate or integrate between the façade and the systems.
[Author: Brian Mulloy, Apigee]