Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
EXTREME 
APIS 
for a better tomorrow 
http://www.aaronmaturen.com/api 1
I'm Aaron. 
• I work at Saginaw Valley State University in Michigan 
• I normally write in PHP and JavaScript 
• I am goin...
I have a small company (Ivory Penguin) to do side jobs 
http://www.aaronmaturen.com/api 3
Interrupt me 
whenever 
http://www.aaronmaturen.com/api 4
Interrupt me if you 
have a question 
It's easy to forget it 
http://www.aaronmaturen.com/api 5
Interrupt me if I'm 
talking too fast 
I get excited easily 
http://www.aaronmaturen.com/api 6
What is an API? 
API => Application Programming Interface 
REST => REpresentational State Transfer 
http://www.aaronmature...
Data is messy. 
http://www.aaronmaturen.com/api 8
Data is confusing. 
http://www.aaronmaturen.com/api 9
Conventions? 
DEAN_ROLE 
CHAIR_ROLE 
EmployeeRole 
DeanRole2 
DeanRole3 
ChairRole2 
ChairRole3 
ChairRole4 
http://www.aa...
Descriptive Names? 
Printed_Text 
http://www.aaronmaturen.com/api 11
Data is everywhere. 
http://www.aaronmaturen.com/api 12
http://www.aaronmaturen.com/api 13
Leverage HTTP 
Create => POST 
Read => Get 
Update => PUT / PATCH 
Delete => DELETE 
http://www.aaronmaturen.com/api 14
Leverage HTTP for Collections 
http://api.svsu.edu/courses 
POST => Update entire collection 
GET => Retrieve the entire c...
Leverage HTTP for elements 
http://api.svsu.edu/courses/ 
courseNumber 
POST => Update a single course element 
GET => Ret...
{json:api} 1 
If you've ever argued with your team about the way your JSON 
responses should be formatted, JSON API is you...
A JSON object MUST be at the root of every document. 
A document's top level SHOULD contain a representation of 
the resou...
{ 
"posts": { 
"id": "1", 
// ... attributes of this post 
} 
} 
http://www.aaronmaturen.com/api 19
{ 
"posts": [{ 
"id": "1" 
// ... attributes of this post 
}, { 
"id": "2" 
// ... attributes of this post 
}] 
} 
http://...
GET /prefixes HTTP/1.1 
Host: api.svsu.edu 
http://www.aaronmaturen.com/api 21
{ 
"prefixes": [ 
{ 
"prefix": "ACCT", 
"description": "Accounting" 
}, 
{ 
"prefix": "ART", 
"description": "Art" 
}, 
.....
Plural v. Singular 
/persons 
/person/23 
Mixing it up starts to get confusing 
/persons 
/persons/23 
/persons/23/courses...
Query Strings 
GET /persons?name=Aaron%20Maturen HTTP/1.1 
Host: api.svsu.edu 
http://www.aaronmaturen.com/api 24
{ 
"persons": [{ 
"firstName": "Aaron", 
"middleInitial": "T", 
"lastName": "Maturen", 
"email": "atmature@svsu.edu", 
"di...
ERROR 
http://www.aaronmaturen.com/api 26
HTTP Status Codes 
http://www.aaronmaturen.com/api 27
2xx is all about success 
200 - Generic everything is OK 
201 - Created something OK 
202 - Accepted but is being processe...
3xx is all about redirection 
301 - Moved permanently 
302 - Moved temporarily 
304 - Not Modified 
http://www.aaronmature...
4xx is all about client errors 
400 - Bad Request (should really be for invalid syntax, but 
some folks use for validation...
5xx is all about service errors 
500 - Something unexpected happened and it is the API's fault 
503 - API is not here righ...
Custom error codes 
and messages 
http://www.aaronmaturen.com/api 32
HTTP/1.0 401 Unauthorized 
Date: Fri, 19 Oct 2014 16:59:59 GMT 
Content-Type: application/vnd.api+json 
{ 
"error": { 
"ty...
HTTP/1.0 401 Unauthorized 
Date: Fri, 19 Oct 2014 16:59:59 GMT 
Content-Type: application/vnd.api+json 
{ 
"error": { 
"ty...
200 OK 
and 
Error Code 
http://www.aaronmaturen.com/api 35
If it's a 2xx code. 
It doesn't get an error code. 
EVER. 
http://www.aaronmaturen.com/api 36
Transformers 
Tables in disguise 
http://www.aaronmaturen.com/api 37
It's normally a very bad idea to 
just output a db table through 
your API 
http://www.aaronmaturen.com/api 38
You're ... 
• revealing your database structure 
• probably returning incorrect value types 
• returning everything 
• tig...
Remember our poorly named fields? 
DEAN_ROLE 
CHAIR_ROLE 
EmployeeRole 
DeanRole2 
DeanRole3 
ChairRole2 
ChairRole3 
Chai...
Those get cleaned up quite nicely 
{ 
"persons": [{ 
"firstName": "Joni", 
"middleInitial": "M", 
"lastName": "Boye-Beaman...
Offices are nicer 
LocationDesc 
BuildingDesc 
PriCampusOffice 
PriCampusPhone 
PriCampusFax 
http://www.aaronmaturen.com/...
Offices are nicer 
{ 
"persons": [{ 
"firstName": "Joni", 
"middleInitial": "M", 
"lastName": "Boye-Beaman", 
"office": { ...
Degrees are nicer 
Degree1 
Degree2 
Degree3 
Degree4 
DegreeInSta1 
DegreeInSta2 
DegreeInSta3 
DegreeInSta4 
http://www....
Degrees are nicer 
{ 
"persons": [{ 
"firstName": "Joni", 
"middleInitial": "M", 
"lastName": "Boye-Beaman", 
"degrees": [...
Hiding Schema Updates 
Before 
'firstName' => $person->nickName, 
After 
'firstName' => $person->firstName, 
http://www.aa...
Hiding Schema Updates 
Before 
'status' => $person->status, 
After 
'status' => $person->status === 'a' ? 'available' : $p...
Objects will be 
related 
http://www.aaronmaturen.com/api 48
Inclusion of Linked Resources 
GET /departments/?embed=colleges.deans HTTP/1.1 
Host: api.svsu.edu 
http://www.aaronmature...
{ 
"departments": [{ 
"department": "CS", 
"colleges": { 
"college": "SC", 
"description": "Science Engineering & Technolo...
Obscurity 
http://www.aaronmaturen.com/api 51
Remember the example from 
before... 
GET /persons/23 HTTP/1.1 
Host: api.svsu.edu 
This is better 
GET /persons/66dc3930-...
Pagination 
GET /persons/teaches=Y HTTP/1.1 
Host: api.svsu.edu 
• Downloading more stuff takes longer 
• Your database mi...
{ 
"persons": [ ...], 
"pagination" : { 
"total": 1262, 
"count": 12, 
"per_page": 12, 
"current_page": 1, 
"total_pages":...
{ 
"persons": [ ...], 
"pagination": { 
"cursors": { 
"after": 12, 
"next_url": "/places?cursor=12&number=12" 
} 
} 
} 
If...
Lions, and Tigers, and FERPA 
Oh my. 
We're not returning anything protected by FERPA to 
anonymous users 
GET /persons?na...
persons: [{}] 
We could have returned an unauthorized 
error (401), but we decided to just act like 
we didn't find anythi...
OAuth to the rescue 
GET /persons?name=Student%20McStudent HTTP/1.1 
Host: api.svsu.edu 
Authorization: Bearer qxacJ57Yo5X...
OAuth Grant Types 
• Authorization Code 
Typical third party workflow, takes user to a common login 
page, they enter thei...
OAuth Grant Types 
• Password (user credentials) 
User Credentials are possibly the easiest way to get an 
access token fo...
OAuth Grant Types 
• Client Credentials 
The application will not have any context of a “user”, but it 
will be able to in...
POST /oauth/access_token HTTP/1.1 
Host: api.svsu.edu 
{ 
grant_type: "password", 
client_id: "98f9bc2f27159248b3e51fa9fd9...
HTTP/1.0 200 OK 
Date: Sun, 19 Oct 2014 16:59:59 GMT 
Content-Type: application/vnd.api+json 
{ 
"access_token": "qxacJ57Y...
What's Next? 
http://www.aaronmaturen.com/api 64
API Clients 
• PHP 
• JavaScript (AngularJS Resources) 
http://www.aaronmaturen.com/api 65
Apps 
• Course Lookup 
• Employee Directory 
• Student Voting 
• Grant logging 
• HealthyU 
http://www.aaronmaturen.com/ap...
Password Authentication 
• Login to the API and the Application simultaneously 
Authorization Code 
• Allow students and t...
Questions? 
Comments? 
Concerns? 
http://www.aaronmaturen.com/api 68
Upcoming SlideShare
Loading in …5
×

Extreme APIs for a better tomorrow

411 views

Published on

It's possible to make a structured, consistent, API that can handle changes to logic and the schema. Sure, it seems like a good plan to dump everything out of the database today, but what are you going to do when something changes down the road? Let's have a talk about some SOLID ways to structure our APIs and keep them from breaking down the road.

Published in: Internet
  • Be the first to comment

  • Be the first to like this

Extreme APIs for a better tomorrow

  1. 1. EXTREME APIS for a better tomorrow http://www.aaronmaturen.com/api 1
  2. 2. I'm Aaron. • I work at Saginaw Valley State University in Michigan • I normally write in PHP and JavaScript • I am going to try to keep this (mostly) langauge agnostic http://www.aaronmaturen.com/api http://www.aaronmaturen.com/api 2
  3. 3. I have a small company (Ivory Penguin) to do side jobs http://www.aaronmaturen.com/api 3
  4. 4. Interrupt me whenever http://www.aaronmaturen.com/api 4
  5. 5. Interrupt me if you have a question It's easy to forget it http://www.aaronmaturen.com/api 5
  6. 6. Interrupt me if I'm talking too fast I get excited easily http://www.aaronmaturen.com/api 6
  7. 7. What is an API? API => Application Programming Interface REST => REpresentational State Transfer http://www.aaronmaturen.com/api 7
  8. 8. Data is messy. http://www.aaronmaturen.com/api 8
  9. 9. Data is confusing. http://www.aaronmaturen.com/api 9
  10. 10. Conventions? DEAN_ROLE CHAIR_ROLE EmployeeRole DeanRole2 DeanRole3 ChairRole2 ChairRole3 ChairRole4 http://www.aaronmaturen.com/api 10
  11. 11. Descriptive Names? Printed_Text http://www.aaronmaturen.com/api 11
  12. 12. Data is everywhere. http://www.aaronmaturen.com/api 12
  13. 13. http://www.aaronmaturen.com/api 13
  14. 14. Leverage HTTP Create => POST Read => Get Update => PUT / PATCH Delete => DELETE http://www.aaronmaturen.com/api 14
  15. 15. Leverage HTTP for Collections http://api.svsu.edu/courses POST => Update entire collection GET => Retrieve the entire collection PUT => Replace the entire collection PATCH => Modify the collection DELETE => Delete the entire collection http://www.aaronmaturen.com/api 15
  16. 16. Leverage HTTP for elements http://api.svsu.edu/courses/ courseNumber POST => Update a single course element GET => Retrieve a single course element PUT => Replace a single course element PATCH => Modify a single course element DELETE => Delete a single course element http://www.aaronmaturen.com/api 16
  17. 17. {json:api} 1 If you've ever argued with your team about the way your JSON responses should be formatted, JSON API is your anti-bikeshedding weapon. By following shared conventions, you can increase productivity, take advantage of generalized tooling, and focus on what matters: your application. 1 http://jsonapi.org/ http://www.aaronmaturen.com/api 17
  18. 18. A JSON object MUST be at the root of every document. A document's top level SHOULD contain a representation of the resource or collection requested. The primary resource(s) SHOULD be keyed either by their resource type or the generic key "data". http://www.aaronmaturen.com/api 18
  19. 19. { "posts": { "id": "1", // ... attributes of this post } } http://www.aaronmaturen.com/api 19
  20. 20. { "posts": [{ "id": "1" // ... attributes of this post }, { "id": "2" // ... attributes of this post }] } http://www.aaronmaturen.com/api 20
  21. 21. GET /prefixes HTTP/1.1 Host: api.svsu.edu http://www.aaronmaturen.com/api 21
  22. 22. { "prefixes": [ { "prefix": "ACCT", "description": "Accounting" }, { "prefix": "ART", "description": "Art" }, ... ] } http://www.aaronmaturen.com/api 22
  23. 23. Plural v. Singular /persons /person/23 Mixing it up starts to get confusing /persons /persons/23 /persons/23/courses http://www.aaronmaturen.com/api 23
  24. 24. Query Strings GET /persons?name=Aaron%20Maturen HTTP/1.1 Host: api.svsu.edu http://www.aaronmaturen.com/api 24
  25. 25. { "persons": [{ "firstName": "Aaron", "middleInitial": "T", "lastName": "Maturen", "email": "atmature@svsu.edu", "division": "Administration & Business Affairs", "department": "Information Technology Services", "program": "Administration & Business Aff.", "title": "Developer", "office": { "location": "SVSU Main Campus", "phone": "989-964-2190", "room": "South Campus Complex B 117", "hours": null }, "degrees": [...], "ferpa": true, "username": "atmature", "faculty": false, "academicDepartment": false ... }] } http://www.aaronmaturen.com/api 25
  26. 26. ERROR http://www.aaronmaturen.com/api 26
  27. 27. HTTP Status Codes http://www.aaronmaturen.com/api 27
  28. 28. 2xx is all about success 200 - Generic everything is OK 201 - Created something OK 202 - Accepted but is being processed async (for a video means encoding, for an image means resizing, etc) http://www.aaronmaturen.com/api 28
  29. 29. 3xx is all about redirection 301 - Moved permanently 302 - Moved temporarily 304 - Not Modified http://www.aaronmaturen.com/api 29
  30. 30. 4xx is all about client errors 400 - Bad Request (should really be for invalid syntax, but some folks use for validation) 401 - Unauthorized (no current user and there should be) 403 - The current user is forbidden from accessing this data 404 - That URL is not a valid route, or the item resource does not exist 405 - Method Not Allowed 410 - Data has been deleted, deactivated, suspended, etc 418 - I'm a teapot http://www.aaronmaturen.com/api 30
  31. 31. 5xx is all about service errors 500 - Something unexpected happened and it is the API's fault 503 - API is not here right now, please try again later 507 - Hard-drive filled up. http://www.aaronmaturen.com/api 31
  32. 32. Custom error codes and messages http://www.aaronmaturen.com/api 32
  33. 33. HTTP/1.0 401 Unauthorized Date: Fri, 19 Oct 2014 16:59:59 GMT Content-Type: application/vnd.api+json { "error": { "type": "OAuthException", "message": "Session has expired at unix time 1385243766. The current unix time is 1385848532." } } http://www.aaronmaturen.com/api 33
  34. 34. HTTP/1.0 401 Unauthorized Date: Fri, 19 Oct 2014 16:59:59 GMT Content-Type: application/vnd.api+json { "error": { "type": "OAuthException", "code": "ERR-01234", "message": "Session has expired at unix time 1385243766. The current unix time is 1385848532." "documentation_url": "/docs/errors/#ERR-01234" } } http://www.aaronmaturen.com/api 34
  35. 35. 200 OK and Error Code http://www.aaronmaturen.com/api 35
  36. 36. If it's a 2xx code. It doesn't get an error code. EVER. http://www.aaronmaturen.com/api 36
  37. 37. Transformers Tables in disguise http://www.aaronmaturen.com/api 37
  38. 38. It's normally a very bad idea to just output a db table through your API http://www.aaronmaturen.com/api 38
  39. 39. You're ... • revealing your database structure • probably returning incorrect value types • returning everything • tightly coupling your api to the database http://www.aaronmaturen.com/api 39
  40. 40. Remember our poorly named fields? DEAN_ROLE CHAIR_ROLE EmployeeRole DeanRole2 DeanRole3 ChairRole2 ChairRole3 ChairRole4 http://www.aaronmaturen.com/api 40
  41. 41. Those get cleaned up quite nicely { "persons": [{ "firstName": "Joni", "middleInitial": "M", "lastName": "Boye-Beaman", "division": "Academic Affairs", "department": "College of Arts & Behavioral Sciences", "title": "Dean College of Arts & Behavioral Sciences", "dean": true, "chair": false ... }] } http://www.aaronmaturen.com/api 41
  42. 42. Offices are nicer LocationDesc BuildingDesc PriCampusOffice PriCampusPhone PriCampusFax http://www.aaronmaturen.com/api 42
  43. 43. Offices are nicer { "persons": [{ "firstName": "Joni", "middleInitial": "M", "lastName": "Boye-Beaman", "office": { "location": "SVSU Main Campus", "phone": "989-964-4062", "room": "Wickes Hall 363", "hours": null }, ... }] } http://www.aaronmaturen.com/api 43
  44. 44. Degrees are nicer Degree1 Degree2 Degree3 Degree4 DegreeInSta1 DegreeInSta2 DegreeInSta3 DegreeInSta4 http://www.aaronmaturen.com/api 44
  45. 45. Degrees are nicer { "persons": [{ "firstName": "Joni", "middleInitial": "M", "lastName": "Boye-Beaman", "degrees": [{ "degree": "Doctor of Philosophy", "from": "State Univ New York-albany" }], ... }] } http://www.aaronmaturen.com/api 45
  46. 46. Hiding Schema Updates Before 'firstName' => $person->nickName, After 'firstName' => $person->firstName, http://www.aaronmaturen.com/api 46
  47. 47. Hiding Schema Updates Before 'status' => $person->status, After 'status' => $person->status === 'a' ? 'available' : $person->status , http://www.aaronmaturen.com/api 47
  48. 48. Objects will be related http://www.aaronmaturen.com/api 48
  49. 49. Inclusion of Linked Resources GET /departments/?embed=colleges.deans HTTP/1.1 Host: api.svsu.edu http://www.aaronmaturen.com/api 49
  50. 50. { "departments": [{ "department": "CS", "colleges": { "college": "SC", "description": "Science Engineering & Technology", "deans": [{ "firstName": "Andrew", "middleInitial": "M", "lastName": "Chubb", ... }] ... }] } http://www.aaronmaturen.com/api 50
  51. 51. Obscurity http://www.aaronmaturen.com/api 51
  52. 52. Remember the example from before... GET /persons/23 HTTP/1.1 Host: api.svsu.edu This is better GET /persons/66dc3930-5928-11e4-8ed6-0800200c9a66 HTTP/1.1 Host: api.svsu.edu http://www.aaronmaturen.com/api 52
  53. 53. Pagination GET /persons/teaches=Y HTTP/1.1 Host: api.svsu.edu • Downloading more stuff takes longer • Your database might not be happy about trying to return 100,000 records in one go • Presentation logic iterating over 100,000 records is also no fun http://www.aaronmaturen.com/api 53
  54. 54. { "persons": [ ...], "pagination" : { "total": 1262, "count": 12, "per_page": 12, "current_page": 1, "total_pages": 107, "next_url": "/persons?page=2&number=12", } } http://www.aaronmaturen.com/api 54
  55. 55. { "persons": [ ...], "pagination": { "cursors": { "after": 12, "next_url": "/places?cursor=12&number=12" } } } If the API returns 12 persons then there might be a next page. http://www.aaronmaturen.com/api 55
  56. 56. Lions, and Tigers, and FERPA Oh my. We're not returning anything protected by FERPA to anonymous users GET /persons?name=Student%20McStudent HTTP/1.1 Host: api.svsu.edu http://www.aaronmaturen.com/api 56
  57. 57. persons: [{}] We could have returned an unauthorized error (401), but we decided to just act like we didn't find anything http://www.aaronmaturen.com/api 57
  58. 58. OAuth to the rescue GET /persons?name=Student%20McStudent HTTP/1.1 Host: api.svsu.edu Authorization: Bearer qxacJ57Yo5XEhzExjsJgLleLoBRXz7kn9ySFB3sY may return persons: [{ firstName: "Student", ... }] http://www.aaronmaturen.com/api 58
  59. 59. OAuth Grant Types • Authorization Code Typical third party workflow, takes user to a common login page, they enter their credentials, they are taken to a page that explains which rights the application would like to have and the user approves it. http://www.aaronmaturen.com/api 59
  60. 60. OAuth Grant Types • Password (user credentials) User Credentials are possibly the easiest way to get an access token for a user. It skips the whole redirect-flow that “Authentication Code” provides Internal Apps Only • Refresh Token Users receive a 401 when the access token expires and the client automatically requests a new one with it's refresh token http://www.aaronmaturen.com/api 60
  61. 61. OAuth Grant Types • Client Credentials The application will not have any context of a “user”, but it will be able to interact with your API. This is useful for CRON jobs, worker processes, daemons or any other sort of background process. • Custom Grant Type You're free to add any new grant types that you would like http://www.aaronmaturen.com/api 61
  62. 62. POST /oauth/access_token HTTP/1.1 Host: api.svsu.edu { grant_type: "password", client_id: "98f9bc2f27159248b3e51fa9fd91a5f9", client_secret: "7329d92ebf23efc145b7370d5f4fbf32", username: "atmature@svsu.edu", password: "secret", scope: "read_users", state: "123456789" } http://www.aaronmaturen.com/api 62
  63. 63. HTTP/1.0 200 OK Date: Sun, 19 Oct 2014 16:59:59 GMT Content-Type: application/vnd.api+json { "access_token": "qxacJ57Yo5XEhzExjsJgLleLoBRXz7kn9ySFB3sY", "token_type": "bearer", "expires": 1400880256, "expires_in": 604800, "refresh_token": "hHgKUskwd9Ukr08CtynO8PjHcV1CZICi1yU3nNmo" } http://www.aaronmaturen.com/api 63
  64. 64. What's Next? http://www.aaronmaturen.com/api 64
  65. 65. API Clients • PHP • JavaScript (AngularJS Resources) http://www.aaronmaturen.com/api 65
  66. 66. Apps • Course Lookup • Employee Directory • Student Voting • Grant logging • HealthyU http://www.aaronmaturen.com/api 66
  67. 67. Password Authentication • Login to the API and the Application simultaneously Authorization Code • Allow students and third parties to access our data • Users are notified that the application is not created by IT and informed of what rights it is requesting http://www.aaronmaturen.com/api 67
  68. 68. Questions? Comments? Concerns? http://www.aaronmaturen.com/api 68

×