Skip to content

Instantly share code, notes, and snippets.

@enguerran
Last active June 1, 2022 13:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enguerran/3c89af7b147a159ae55e to your computer and use it in GitHub Desktop.
Save enguerran/3c89af7b147a159ae55e to your computer and use it in GitHub Desktop.
API

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

write simple URLs

  • Nouns are good; verbs are bad
  • keep simple things simple
  • keep your base URL simple and intuitive
  • 2 base URLs per resource
  • /dogs for collections; /dogs/1234 for item
  • POST /dogs create a new dog
  • GET /dogs list dogs
  • PUT /dogs bulk update dogs
  • DELETE /dogs delete all dogs
  • POST /dogs/1234 Error
  • GET /dogs Show Bo
  • PUT /dogs If exists update Bo; else Error
  • DELETE /dogs delete Bo
  • use plural nouns
  • be consistent
  • concrete names are better than abstract
  • simplify associations
  • GET /owners/5678/dogs get all dogs belonging to specific owner
  • POST /owners/5678/dogs to create a new dog for that owner
  • you should not need deeper URL than /resource/identifier/resource

complexity behind the '?'

  • sweep complexity behind the '?'
  • GET /dogs?color=red&state=running&location=park get all red dogs running in the park

handling errors

  • 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

versioning

  • 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, ...)

URLs or headers?

  • 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

pagination and partial response

  • /dogs?fields=name,color,location returns only needed fields for developer
  • /dogs?limit=25&offset=50 returns the 25 rows starting at 50s row

handle non resource

  • user verbs not nouns: /convert?from=EUR&to=CNY&amount=100

multiple formats

  • Google Data: ?alt=json
  • Foursquare: venue.json
  • Digg: Accept: application/json or ?type=json
  • recommandation: /dogs/1234.json
  • use json as default format

attribute names

  • var myObject = JSON.parse(response); var timing = myObject.createdAt;
  • json/javascript conventions

search

  • use resourcefull API: /dogs?q=red+running+park
  • multiple resources: /search?q=fluffy+fur
  • return specific format: /search.json?q=fluffy+fur or /search.xml?q=fluffy+fur

consolidate API requests in one subdomain

  • 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

authentication

  • use OAuth - OAuth 2.0

Full example requests

  • 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

API Façade Pattern

  • 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:
  1. Design the ideal API. The API design should be self-consistent.
  2. Implement the design with data stubs.
  3. Mediate or integrate between the façade and the systems.

[Author: Brian Mulloy, Apigee]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment