$30 off During Our Annual Pro Sale. View Details »

User Experience Patterns for APIs

User Experience Patterns for APIs

Slides from RailsClub 2012 in Moscow.

Wynn Netherland

September 15, 2012
Tweet

More Decks by Wynn Netherland

Other Decks in Programming

Transcript

  1. WYNN NETHERLAND
    User Experience
    Patterns for APIs

    View Slide

  2. Howdy!

    View Slide

  3. Wynn Netherland
    My name is

    View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. .com

    View Slide

  8. View Slide

  9. View Slide

  10. I write API wrappers

    View Slide

  11. View Slide

  12. View Slide

  13. UX Patterns for APIs
    and anti-patterns
    ^

    View Slide

  14. Support curling
    PATTERN

    View Slide

  15. curl -i https://api.github.com/users/defunkt
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    Content-Length: 692
    X-Content-Type-Options: nosniff
    X-RateLimit-Remaining: 4997
    X-RateLimit-Limit: 5000
    Cache-Control: public, s-maxage=60, max-age=60
    Vary: Accept
    X-GitHub-Media-Type: github.beta
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT
    {
    "following": 212,
    "type": "User",
    "html_url": "https://github.com/defunkt",
    "location": "San Francisco",
    "hireable": true,

    View Slide

  16. curl -i -u pengwynn \
    https://api.github.com/user

    View Slide

  17. curl -i -u pengwynn \
    https://api.github.com/user
    include response headers

    View Slide

  18. curl -i -u pengwynn \
    https://api.github.com/user
    use Basic Auth, prompt for password

    View Slide

  19. Security mazes
    ANTI-PATTERN

    View Slide

  20. View Slide

  21. OAuth is painful.
    OAuth2 hurts less.

    View Slide

  22. View Slide

  23. Insane URLs
    ANTI-PATTERN

    View Slide

  24. http://sandbox.api.shopping.com/publisher/
    3.0/rest/GeneralSearch?
    hybridSortType=relevance&productSortType=r
    elevance&offerSortType=store-
    name&productReviewSortType=review-date

    View Slide

  25. http://maps.googleapis.com/maps/api/
    staticmap?center=Brooklyn+Bridge,New
    +York,NY&zoom=13&size=600x300&maptype=road
    map&markers=color:blue%7Clabel:S
    %7C40.702147,-74.015794&markers=color:gree
    n%7Clabel:G%7C40.711614,-74.012318
    &markers=color:red%7Ccolor:red%7Clabel:C
    %7C40.718217,-73.998284&sensor=false

    View Slide

  26. Maximize the payload
    PATTERN

    View Slide

  27. {
    "uri": "/pengwynn/githubbers",
    "name": "GitHubbers",
    "full_name": "@pengwynn/githubbers",
    "description": "",
    "mode": "public",
    "user": {
    "id": 14100886,
    "favourites_count": 275,
    "profile_image_url": "http://a0.twimg.com/profile_ima...",
    "profile_background_tile": false,
    "profile_sidebar_fill_color": "DDEEF6",
    "verified": false,
    "location": "Denton, TX",
    "utc_offset": -21600,
    "name": "Wynn Netherland",
    "lang": "en",
    "is_translator": false,
    "default_profile": true,
    "profile_background_color": "C0DEED",
    "protected": false,
    "contributors_enabled": false,
    "time_zone": "Central Time (US & Canada)",
    "profile_background_image_url": "http://a0.twimg.com/images/themes/...",
    "profile_link_color": "0084B4",
    "description": "Christian, husband, father, GitHubber, Co-host...",
    "geo_enabled": true,
    "listed_count": 388,
    "show_all_inline_media": true,
    "notifications": false,
    "id_str": "14100886",
    "statuses_count": 7178,
    "profile_image_url_https": "https://si0.twimg.com/profile_images/2221455972/

    View Slide

  28. {
    "uri": "/pengwynn/githubbers",
    "name": "GitHubbers",
    "full_name": "@pengwynn/githubbers",
    "description": "",
    "mode": "public",
    "user": {
    "id": 14100886,
    "favourites_count": 275,
    "profile_image_url": "http://a0.twimg.com/profile_ima...",
    "profile_background_tile": false,
    "profile_sidebar_fill_color": "DDEEF6",
    "verified": false,
    "location": "Denton, TX",
    "utc_offset": -21600,
    "name": "Wynn Netherland",
    "lang": "en",
    "is_translator": false,
    "default_profile": true,
    "profile_background_color": "C0DEED",
    "protected": false,
    "contributors_enabled": false,
    "time_zone": "Central Time (US & Canada)",
    "profile_background_image_url": "http://a0.twimg.com/images/themes/...",
    "profile_link_color": "0084B4",
    "description": "Christian, husband, father, GitHubber, Co-host...",
    "geo_enabled": true,
    "listed_count": 388,
    "show_all_inline_media": true,
    "notifications": false,
    "id_str": "14100886",
    "statuses_count": 7178,
    "profile_image_url_https": "https://si0.twimg.com/profile_images/2221455972/
    Full User object

    View Slide

  29. Rock the cache
    PATTERN

    View Slide

  30. curl -I https://api.github.com/users/defunkt
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    Content-Length: 692
    X-Content-Type-Options: nosniff
    X-RateLimit-Remaining: 4997
    X-RateLimit-Limit: 5000
    Cache-Control: public, s-maxage=60, max-age=60
    Vary: Accept
    X-GitHub-Media-Type: github.beta
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT

    View Slide

  31. curl -I https://api.github.com/users/defunkt
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    Content-Length: 692
    X-Content-Type-Options: nosniff
    X-RateLimit-Remaining: 4997
    X-RateLimit-Limit: 5000
    Cache-Control: public, s-maxage=60, max-age=60
    Vary: Accept
    X-GitHub-Media-Type: github.beta
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT

    View Slide

  32. curl -I https://api.github.com/users/defunkt
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    Content-Length: 692
    X-Content-Type-Options: nosniff
    X-RateLimit-Remaining: 4997
    X-RateLimit-Limit: 5000
    Cache-Control: public, s-maxage=60, max-age=60
    Vary: Accept
    X-GitHub-Media-Type: github.beta
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT
    Cache policy

    View Slide

  33. curl -I https://api.github.com/users/defunkt
    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    Content-Length: 692
    X-Content-Type-Options: nosniff
    X-RateLimit-Remaining: 4997
    X-RateLimit-Limit: 5000
    Cache-Control: public, s-maxage=60, max-age=60
    Vary: Accept
    X-GitHub-Media-Type: github.beta
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT
    Fingerprint

    View Slide

  34. curl -I \
    -H 'If-None-Match:"ef742caec0c19e2169ffb05e7d200d17" \
    https://api.github.com/users/defunkt
    HTTP/1.1 304 Not Modified
    Server: nginx
    Date: Wed, 12 Sep 2012 15:51:39 GMT
    Connection: keep-alive
    Status: 304 Not Modified
    X-RateLimit-Limit: 5000
    X-Content-Type-Options: nosniff
    Vary: Accept
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    X-RateLimit-Remaining: 4997
    Last-Modified: Wed, 12 Sep 2012 01:38:14 GMT
    Cache-Control: public, s-maxage=60, max-age=60

    View Slide

  35. curl -H 'If-None-Match:"ef742caec0c19e2169ffb05e7d200d17" \
    https://api.github.com/users/defunkt
    HTTP/1.1 304 Not Modified
    Server: nginx
    Date: Wed, 12 Sep 2012 15:51:39 GMT
    Connection: keep-alive
    Status: 304 Not Modified
    X-RateLimit-Limit: 5000
    X-Content-Type-Options: nosniff
    Vary: Accept
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    X-RateLimit-Remaining: 4997
    Last-Modified: Wed, 12 Sep 2012 01:38:14 GMT
    Cache-Control: public, s-maxage=60, max-age=60

    View Slide

  36. $ curl -i https://api.github.com/user
    HTTP/1.1 200 OK
    Cache-Control: private, max-age=60
    ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
    Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
    Status: 200 OK
    Vary: Accept, Authorization, Cookie
    X-RateLimit-Limit: 5000
    X-RateLimit-Remaining: 4996
    $ curl -i https://api.github.com/user -H "If-Modified-Since: Thu, 05 Jul 2012
    15:31:30 GMT"
    HTTP/1.1 304 Not Modified
    Cache-Control: private, max-age=60
    Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
    Status: 304 Not Modified
    Vary: Accept, Authorization, Cookie
    X-RateLimit-Limit: 5000
    X-RateLimit-Remaining: 4996
    $ curl -i https://api.github.com/user -H 'If-None-Match:
    "644b5b0155e6404a9cc4bd9d8b1ae730"'
    HTTP/1.1 304 Not Modified
    Cache-Control: private, max-age=60
    ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
    Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
    Status: 304 Not Modified
    Vary: Accept, Authorization, Cookie
    X-RateLimit-Limit: 5000
    X-RateLimit-Remaining: 4996

    View Slide

  37. Dogfood it
    PATTERN

    View Slide

  38. Build
    something
    meaningful
    with your API.

    View Slide

  39. Build
    something
    meaningful
    with your API.
    Janky

    View Slide

  40. Build
    something
    meaningful
    with your API.
    Janky
    Heaven

    View Slide

  41. Build
    something
    meaningful
    with your API.
    Janky
    Heaven
    Monitors

    View Slide

  42. Build
    something
    meaningful
    with your API.
    Janky
    Team
    Heaven
    Monitors

    View Slide

  43. Build
    something
    meaningful
    with your API.
    Janky
    Team
    Hire
    Heaven
    Monitors

    View Slide

  44. Build
    something
    meaningful
    with your API.
    Janky
    Team
    Hire
    Heaven
    Monitors
    The Setup™

    View Slide

  45. Build
    something
    meaningful
    with your API.
    Janky
    Team
    Hire
    Heaven
    Monitors
    The Setup™
    Graph Store

    View Slide

  46. How GitHub uses the
    GitHub API.

    View Slide

  47. How GitHub uses the
    GitHub API.
    AuthN

    View Slide

  48. How GitHub uses the
    GitHub API.
    AuthN
    AuthZ

    View Slide

  49. How GitHub uses the
    GitHub API.
    AuthN
    AuthZ
    Merging

    View Slide

  50. How GitHub uses the
    GitHub API.
    AuthN
    AuthZ
    Merging
    Commit Status

    View Slide

  51. How GitHub uses the
    GitHub API.
    AuthN
    AuthZ
    Merging
    Commit Status
    GFM

    View Slide

  52. Oh, and native apps.

    View Slide

  53. Oh, and native apps.
    GitHub for Mac

    View Slide

  54. Oh, and native apps.
    GitHub for Mac
    GitHub for Windows

    View Slide

  55. PATTERN
    Use HTTP status codes

    View Slide

  56. HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 200 OK
    ETag: "ef742caec0c19e2169ffb05e7d200d17"
    Last-Modified: Tue, 11 Sep 2012 02:52:21 GMT
    {
    "error_code": 1234,
    "error": "User not found"
    }

    View Slide

  57. HTTP/1.1 404 Not Found
    Server: nginx
    Date: Wed, 12 Sep 2012 14:07:43 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Status: 404 Not Found

    View Slide

  58. Confusing header with body
    ANTI-PATTERN

    View Slide

  59. Harsh rate limits
    ANTI-PATTERN

    View Slide

  60. $ curl -i https://api.github.com/users/
    whatever?
    client_id=xxxxxxxxxxxxxx&client_secret=yyy
    yyyyyyyyyyyyyyyyyy
    HTTP/1.1 200 OK
    Status: 200 OK
    X-RateLimit-Limit: 12500
    X-RateLimit-Remaining: 11966

    View Slide

  61. Announce breaking changes
    PATTERN

    View Slide

  62. View Slide

  63. Make documentation obvious
    PATTERN

    View Slide

  64. View Slide

  65. View Slide

  66. View Slide

  67. View Slide

  68. Create awesome guides
    PATTERN

    View Slide

  69. View Slide

  70. View Slide

  71. View Slide

  72. Consoles
    PATTERN

    View Slide

  73. View Slide

  74. View Slide

  75. ANTI-PATTERN
    Endless terms of service changes

    View Slide

  76. Inconsistency
    ANTI-PATTERN

    View Slide

  77. POST /gists/:id/fork
    POST /repos/:user/:repo/merges

    View Slide

  78. Fast, transparent
    support
    PATTERN

    View Slide

  79. View Slide

  80. Free samples
    PATTERN

    View Slide

  81. View Slide

  82. Mashup friendly
    PATTERN

    View Slide

  83. JSONP

    View Slide

  84. $ curl https://api.github.com?callback=foo
    foo({
    "meta": {
    "status": 200,
    "X-RateLimit-Limit": "5000",
    "X-RateLimit-Remaining": "4966",
    "Link": [ // pagination headers and
    other links
    ["https://api.github.com?page=2",
    {"rel": "next"}]
    ]
    },
    "data": {
    // the data
    }
    })

    View Slide

  85. CORS

    View Slide

  86. $ curl -i https://api.github.com \
    -H "Origin: http://calendaraboutnothing.com"
    HTTP/1.1 302 Found
    Access-Control-Allow-Origin: http://calendaraboutnothing.com
    Access-Control-Expose-Headers: Link, X-RateLimit-Limit, X-
    RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
    Access-Control-Allow-Credentials: true

    View Slide

  87. $ curl -i https://api.github.com \
    -H "Origin: http://calendaraboutnothing.com"
    -X OPTIONS
    HTTP/1.1 204 No Content
    Access-Control-Allow-Origin: http://calendaraboutnothing.com
    Access-Control-Allow-Headers: Authorization, X-Requested-With
    Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
    Access-Control-Expose-Headers: Link, X-RateLimit-Limit, X-
    RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
    Access-Control-Max-Age: 86400
    Access-Control-Allow-Credentials: true

    View Slide

  88. Streaming
    PATTERN

    View Slide

  89. Persistent HTTP

    View Slide

  90. Updates as they happen

    View Slide

  91. View Slide

  92. Thanks!

    View Slide