A look at API design
featuring the BringIt API

carlos.justiniano@gmail.com
API Design Goals
Good APIs are designed with end
users in mind
● Ease of use is important!
● The API should be clear and consistent
●

If y...
What should an API do?
●
●
●
●
●

be easy to learn and use
should be difficult to misuse
should be easy to evolve over tim...
An API should be testable
APIs should be testable (yes, I repeated that)
By testable I mean that one should be able to
wri...
An API should be testable
In addition to documentation, APIs should have
a site where developers can interactively test
in...
API Red Flags
● It’s a red flag when you can’t find what you’
re looking for in an API
● … and when you can’t come up with...
APIs in the wild
Lots of companies have APIs...
●
●
●
●

https://dev.twitter.com/docs/api/1.1
http://www.wunderground.com/weather/api/
http...
Why does this matter?
Because we can learn from
what others are doing
Almost all APIs in the wild follow an
architectural approach, called REST
● REST, stands for REpresentational State
Transf...
Levels of REST
Leonard Richardson described these three
levels of REST which is known today as the
Richardson Maturity Mod...
Levels of REST
Level Two: is about using HTTP verbs to
define actions on resources
GET https://domain.com/api/v1/profile/u...
Levels of REST
Level Three: is about using hyperlinks in the
data returned to allow for the navigation of
URIs
Example:
{
...
REST usage
As mentioned earlier, most APIs don’t fully
implement REST
● Most expose resources - so level one
support is al...
REST vs. RESTful
So lack of full REST support (buy in) results in
varied support of REST. We say that an API is
RESTful if...
To REST or not to REST?
When it comes to API
design you can follow a
standard - or do your own
thing...
… then explain later what
the $%^& you were
thinking
BringIt API
Cleanup opportunities
Good News!
As I reviewed the BringIt API I realized it’s
actually in pretty good shape - for a first pass!
With some impro...
BringIt API
appmessages/

challenge

sandbox

game/(?P<game_id>d+)/

u/read/

(?P<chal_id>w+)/join/

u/delete/

(?P<chal_i...
BringIt API
ems

Should be combined into facebook
not an API?
gamesession

fbhost

startgame/(?P<game_id>d+)/
landing/

re...
BringIt API
active/

recommend/

member.urls

activate/(?P<inventory_id>w+)/
(?P<game_id>d+)/

solo/

challenge.urls

rede...
BringIt API
linkedfriends/

fb_share_event/

badges/

fb_share_ibm/

goals/

fb_like/

balance/

dev_fb_unlike/

sent/

de...
Disclaimer for the last set
of slides
That data dump represents Django views
some of which are not actual API call
Some of what follows is
opinionated...
But all of it is up for discussion!
API Path should be separate
This would provide a logical place to look when
trying to understand the API layout
Would allo...
API Path should be separate
The API shouldn’t necessarily have a direct 1-1
relationship to a specific data model
Examples...
APIs should be versioned
consider:
https://www.bringit.com/api/v1/mission
Module names could be singular
rather than plural
Examples:
● appmessage instead of appmessages
○ or better yet: /mesage

...
Avoid using abbreviations in URIs
Abbreviations introduce conceptual overhead,
which doesn’t help when trying to keep thin...
Names used in API should be
lowercase
Currently mixed case is used which leads a
developer to wonder where mixed case is u...
Standardized API names
● Use lowercase: rematch
● Don’t use camel case: wagerAmounts
● Don’t use snake case: inbox_open
Ab...
Consider using actual HTTP returns
values
In our API we almost always return HTTP 200
when we should consider returning HT...
Use HTTP action verbs to minimize
API bloat
In appmessages we have u/read and u/delete
Using HTTP action verbs we would ha...
Use HTTP action verbs to minimize
API bloat
HTTP PUT can be used to queue messages
and HTTP POST can be used to update
exi...
Use HTTP action verbs to minimize
API bloat
● One of the biggest reasons why developers
don’t use PUT and DELETE is becaus...
API should be grouped by resource
type
When deciding how an API call should be
grouped ask the question:
What type of reso...
API should be grouped by resource
type
gifting, invite, challenge, facebook, should all
be in their own group
Examples:
fb...
Resource types should not be
described by multiple names
User and Member are confusing
If goal is to avoid confusion with ...
Avoid the use of compound API
names
Example:
● in challenge: wagerAmount
● in user: linkedfriends, invitesent
Avoid having both single and plural
versions of an API name
Examples:
● wagerAmount and wagerAmounts
A single resource “wa...
Avoid use of action words in API
Example:
● In challenge the word create is used for
solo_create and h2h_create only param...
APIs should have a private and
public face
Private APIs (those starting with dev_) should
be controlled by policies on the...
Rename dev_ API calls
Private APIs are still API calls like any other. In
fact, many APIs might be used internally
between...
Bandwidth optimizations
Consider using ?_body=false to tell the server
that you don’t care about a returned response
body ...
Bandwidth optimizations
Consider returning results in batches, ala
paging
So return first 20 items then allow client to
re...
Topics for future consideration
● API rate metering
● Extended security (OAuth)
Closing thoughts
Today APIs are in widespread use
We don't need to look far for examples of clean
APIs
Many packages exist...
Upcoming SlideShare
Loading in...5
×

API presentation

373

Published on

A look at API design considerations

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
373
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

API presentation

  1. 1. A look at API design featuring the BringIt API carlos.justiniano@gmail.com
  2. 2. API Design Goals
  3. 3. Good APIs are designed with end users in mind ● Ease of use is important! ● The API should be clear and consistent ● If you had to guess where you might find a particular piece of functionality you should be able to guess correctly or be fairly close! ● Design against standards and don’t invent your own ○ Do this for the same reasons we all agree to use frameworks. ● Good documentation is vital
  4. 4. What should an API do? ● ● ● ● ● be easy to learn and use should be difficult to misuse should be easy to evolve over time should do one thing and do it well should be easy to explain - if not, perhaps it’ s not doing one thing well? ● lend itself to reuse to avoid having other programmers warp the API to deal with it in a sane way
  5. 5. An API should be testable APIs should be testable (yes, I repeated that) By testable I mean that one should be able to write integration tests which demonstrate working API calls In contrast, unit test should be mocked
  6. 6. An API should be testable In addition to documentation, APIs should have a site where developers can interactively test individual API calls
  7. 7. API Red Flags ● It’s a red flag when you can’t find what you’ re looking for in an API ● … and when you can’t come up with a good name for the API call ● Good API names are vital! “The names are the API talking back to you - so listen to them.” - Joshua Bloch, Google Talks, Jan 2007
  8. 8. APIs in the wild
  9. 9. Lots of companies have APIs... ● ● ● ● https://dev.twitter.com/docs/api/1.1 http://www.wunderground.com/weather/api/ http://developer.yahoo.com/boss/ https://developers.google. com/maps/documentation/javascript/3. exp/reference ● https://www.dropbox. com/developers/core/docs ● http://dashboard.swrve.com/help/docs
  10. 10. Why does this matter? Because we can learn from what others are doing
  11. 11. Almost all APIs in the wild follow an architectural approach, called REST ● REST, stands for REpresentational State Transfer. REST isn’t a standard, but rather an architectural approach / recommendation ● Most APIs claiming to be REST don’t fully implement REST concepts ● There are three widely accepted levels of REST, most APIs implement most of the first level, some implement parts of the second level, and only few implement the third level of the recommendations
  12. 12. Levels of REST Leonard Richardson described these three levels of REST which is known today as the Richardson Maturity Model Level One: is all about treating URIs as resources. https://domain.com/api/v1/profile/uid/1 returns a profile with a UID of 1
  13. 13. Levels of REST Level Two: is about using HTTP verbs to define actions on resources GET https://domain.com/api/v1/profile/uid/1 PUT https://domain.com/api/v1/profile/uid/1 POST https://domain.com/api/v1/profile/uid/1 DELETE https://domain.com/api/v1/profile/uid/1
  14. 14. Levels of REST Level Three: is about using hyperlinks in the data returned to allow for the navigation of URIs Example: { “href”: “https://site.com/api/v1/profile/uid/1” :… }
  15. 15. REST usage As mentioned earlier, most APIs don’t fully implement REST ● Most expose resources - so level one support is almost a given ● For level two, most only support HTTP GET/POST - many lack support for PUT and DELETE ● Level three support for Hyperlinks is unsupported by most APIs
  16. 16. REST vs. RESTful So lack of full REST support (buy in) results in varied support of REST. We say that an API is RESTful if it attempts to follow REST guidelines, namely level one and two on the Richardson Maturity (scale) Model It turns out that even limited REST support can lead to some consensus regarding API construction. This is a GOOD thing!
  17. 17. To REST or not to REST?
  18. 18. When it comes to API design you can follow a standard - or do your own thing...
  19. 19. … then explain later what the $%^& you were thinking
  20. 20. BringIt API Cleanup opportunities
  21. 21. Good News! As I reviewed the BringIt API I realized it’s actually in pretty good shape - for a first pass! With some improvements we’ll have a version 2 API that will be easier to use and model what others are doing This will make it more easily accepted by external developers who already have experience with industry APIs
  22. 22. BringIt API appmessages/ challenge sandbox game/(?P<game_id>d+)/ u/read/ (?P<chal_id>w+)/join/ u/delete/ (?P<chal_id>w+)/standings/ b/read/ (?P<chal_id>w+)/payout/ b/read/(?P<message_id>w+)/ (?P<chal_id>w+)/rank/ create/ activityfeed wagerAmount/ activityfeed/(?P<context>w+)/ payout/(?P<game_id>d+)/ activityfeed/(?P<context>w+)/(?P<game_id>d+)/ wagerAmounts/ flush_notification_queue/(?P<uid>d+)/ gen_notification_queue/(?P<uid>d+)/ create/(?P<game_id>d+)/(?P<wager_amount>d+)/(? P<challengee_id>d+)/ status/(?P<challenge_id>w+)/(?P<action>w+)/ inbox_open/ rematch/(?P<challenge_id>w+)/ authenticate/ remind/(?P<challenge_id>w+)/ authenticate.urls history/ iframe/(?P<partner_id>d+)/ registerguest/ registeruser/ auth/ partner_auth/ contact / email contact?
  23. 23. BringIt API ems Should be combined into facebook not an API? gamesession fbhost startgame/(?P<game_id>d+)/ landing/ reportscore/ iframe/ gameupdate/ connect/ site/ gameroom payments/ / channel/ currency_object/(?P<partner_id>d+)/ gifting fbproduct/(?P<partner_id>d+)/(? P<category>currency|tournament|missiontask)/(?P<item_id>[azA-Z_0-9-.]+)/ currently in member.urls gifting/ giftsend/ fbfulfillment/ likecount/ giftredeem/(?P<gift_request_id>d+)/(?P<to_id>d+)/(? P<from_id>d+)/ gifter_rewards/ fbsocial / gifttest/ h2h/ challenge.urls login/ test/ noauth/ requesttagger/ inventory/ / inventory.urls
  24. 24. BringIt API active/ recommend/ member.urls activate/(?P<inventory_id>w+)/ (?P<game_id>d+)/ solo/ challenge.urls redeem/(?P<game_id>d+)/(?P<item_type>w+)/ leaderboard/ leaderboard.urls store/ store.urls update/ / dev_reset_global/(?P<game_id>d+)/ (?P<game_id>d+)/ dev_reset_friends/(?P<game_id>d+)/(?P<user_id>d+)/ purchase/(?P<inventory_id>w+)/ earn/(?P<inventory_id>d+)/ purchase/(?P<game_id>d+)/(?P<item_type>w+) missions/ missions.urls skip/ tasklist/ taskpaytocomplete/(?P<task_id>w+)/ purchase/(?P<game_id>d+)/(?P<item_type>w+)/(? P<quantity>d+)/ earn/(?P<game_id>d+)/(?P<item_type>w+) currency_paytables/ missionpaytounlockslot/ dev_taskcomplete/(?P<task_id>w+)/ dev_generatemissioncompletedmessage/(?P<mission_id>w+)/ swrve/ swrve.urls tournaments/ challenge.urls dev_generatetaskcompletedmessage/(?P<task_id>w+)/ dev_resetmission/(?P<mission_id>w+)/ dev_resetallmissions/ dev_resetallandgrantmission/(?P<mission_id>d+)/ user/ member.urls / is_new_user/ (?P<user_id>d+)/$ game/(?P<game_id>d+)/
  25. 25. BringIt API linkedfriends/ fb_share_event/ badges/ fb_share_ibm/ goals/ fb_like/ balance/ dev_fb_unlike/ sent/ dev_set_first_time_user/ gifting/ tutorial/(?P<tutorial_name>w+)/step/(?P<step>w+)/ giftsend/ daily_bonus_prize/ giftredeem/(?P<gift_request_id>d+)/(?P<to_id>d+)/(? P<from_id>d+)/ gifter_rewards/ invite/ invitesent/(?P<app_request>d+)/ redeemcount/ dev_setredeemcount/(?P<count>d+)/ fb_notification/ arcadeinvite/recommend/ arcadeinvite/(?P<action>accept|decline|drop)/reply/(? P<sender_id>d+)/ arcadeinvite/ xp_info/ dev_setxp/(?P<xp_value>d+)/ fb_share/(?P<share_type>w+)/ ping/ heartbeat/ member.urls
  26. 26. Disclaimer for the last set of slides That data dump represents Django views some of which are not actual API call
  27. 27. Some of what follows is opinionated... But all of it is up for discussion!
  28. 28. API Path should be separate This would provide a logical place to look when trying to understand the API layout Would allow for a separation between views and API. It might be desirable to have view handlers which are not considered public API
  29. 29. API Path should be separate The API shouldn’t necessarily have a direct 1-1 relationship to a specific data model Examples: https://bringit.com/api/member https://api.bringit.com/member
  30. 30. APIs should be versioned consider: https://www.bringit.com/api/v1/mission
  31. 31. Module names could be singular rather than plural Examples: ● appmessage instead of appmessages ○ or better yet: /mesage ● mission instead of missions ● tournament instead of tournaments
  32. 32. Avoid using abbreviations in URIs Abbreviations introduce conceptual overhead, which doesn’t help when trying to keep things simple and clear Examples: ● appmessages: u/read, u/delete, b/read
  33. 33. Names used in API should be lowercase Currently mixed case is used which leads a developer to wonder where mixed case is used and where it is not
  34. 34. Standardized API names ● Use lowercase: rematch ● Don’t use camel case: wagerAmounts ● Don’t use snake case: inbox_open Above all - be consistent!
  35. 35. Consider using actual HTTP returns values In our API we almost always return HTTP 200 when we should consider returning HTTP 201 and other values such as 40x and 50x The idea is that an HTTP client should be able to correctly process HTTP messages without having to examine the JSON payload
  36. 36. Use HTTP action verbs to minimize API bloat In appmessages we have u/read and u/delete Using HTTP action verbs we would have: GET https://bringit.com/api/v1/appmessage/ and DELETE https://bringit.com/api/v1/appmessage * appmessage is the resource and GET and DELETE are actions against the resource
  37. 37. Use HTTP action verbs to minimize API bloat HTTP PUT can be used to queue messages and HTTP POST can be used to update existing messages This saves us from potentially creating API such as: ● ● ● ● appmessage/readmessage appmessage/deletemessage appmessage/addmessage appmessage/updatemessage
  38. 38. Use HTTP action verbs to minimize API bloat ● One of the biggest reasons why developers don’t use PUT and DELETE is because it’s not supported by older web browsers ● Few developers know that there are workarounds for this: ○ Simply add an HTTP header called X-HTTP-MethodOverride: ■ X-HTTP-Method-Override: PUT ■ X-HTTP-Method-Override: DELETE ○ Google it for more info!
  39. 39. API should be grouped by resource type When deciding how an API call should be grouped ask the question: What type of resource is this? Don’t overload groups Example: see the members django application
  40. 40. API should be grouped by resource type gifting, invite, challenge, facebook, should all be in their own group Examples: fbshare should be /facebook/share and should probably not be found under the member group Same applies to lots of the API found in the member
  41. 41. Resource types should not be described by multiple names User and Member are confusing If goal is to avoid confusion with Django user then member should be used exclusively
  42. 42. Avoid the use of compound API names Example: ● in challenge: wagerAmount ● in user: linkedfriends, invitesent
  43. 43. Avoid having both single and plural versions of an API name Examples: ● wagerAmount and wagerAmounts A single resource “wager” should return a single wager when and id is provided and a list of wagers when an id is not provided
  44. 44. Avoid use of action words in API Example: ● In challenge the word create is used for solo_create and h2h_create only parameters differ When possible use HTTP VERBS to specify actions
  45. 45. APIs should have a private and public face Private APIs (those starting with dev_) should be controlled by policies on the web server This allows for private APIs to be called from known IPs / gateways and blocked from public use
  46. 46. Rename dev_ API calls Private APIs are still API calls like any other. In fact, many APIs might be used internally between distributed infrasture components and not exposed for general or external use Visibility should be controlled by web server policies
  47. 47. Bandwidth optimizations Consider using ?_body=false to tell the server that you don’t care about a returned response body and that you’ll instead look at the HTTP return code only Add support for selective field retrieval using sets, example: https://domain.com/api/v1/user?fields=(UID, firstName,lastName)
  48. 48. Bandwidth optimizations Consider returning results in batches, ala paging So return first 20 items then allow client to request next 20 items etc… Also allow client to specify how many items it would like to receive This allows for overriding small batches if necessary
  49. 49. Topics for future consideration ● API rate metering ● Extended security (OAuth)
  50. 50. Closing thoughts Today APIs are in widespread use We don't need to look far for examples of clean APIs Many packages exist for your programming language of choice which help simplify using RESTful services
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×