SlideShare a Scribd company logo
Sumit Amar
@ChiefCoder
October 22, 2019
Api design and usability
• Be REST Assured (RESTfulness)
• HATEOAS
• ODATA for Data Retrieval
• Webhooks / Callbacks
• Resources / Entities Depiction
• HTTPVerb Usage
• Entity Relationships
• Status Codes
• Idempotency
• Pluralized nouns for entities
/users
• Actions using HTTP methods
GET /users
• Instances vs Collections
GET /users (returns a collection)
GET /users/1a (returns an instance)
• GET : Retrieve an instance or collection.
• POST : Creates an entity record.
• PUT : Updates a wholesome entity given its
ID.
• DELETE: Removes an entity given its ID
• PATCH: Partially updates an entity given its ID
• OPTIONS: Returns list of HTTP methods
available for an entity
• POST /players
{
"name":"A B",
"country_code":"US",
"phone":"000 000 0000"
}
Response 201 Created
{
"id":"1a",
"name":"A B",
"country_code":"US",
"phone":"000 000 0000"
}
• POST /players/1a/trophies
{
"game":"Mario",
"trophy_name":"Champion"
}
Response: 201 Created
{
"id":"1t",
"game":"Mario",
"trophy_name":"Champion"
}
• GET /players/1a
{
”id":”1a",
"name":"A B",
"country_code":"US",
"phone":"000 000 0000",
"trophies":[
{
"id":"1t",
"game":"Mario",
"trophy_name":"Champion"
},
{
"id":"2t",
"game":"Contra",
"trophy_name":"Champion"
}
]
}
200 OK – ResponseOK. Should be used in GET (or PUT calls containing modified entity)
201 Created – Returned by a synchronous POST call creates an entity.
202 Accepted – Result of an long running operation by a POST call.
204 No Content – Result of a synchronous operation by a DELETE or PUT/PATCH
304 Not Modified – A cached response is returned
400 Bad Request – A malformed JSON request is sent
401 Unauthorized – API user is not authenticated. Bad credentials.
403 Forbidden – API user is not authorized. User roles don’t allow invoking an endpoint
409 Conflict – A race condition is found (validation of updated/modified timestamp
failed)
404 Not Found – Record for provided ID is not found, in case of GET, DELETE, PUT,
PATCH
408 RequestTimeout – Server couldn’t process the request in a specified time limit
414 URIToo Long – When the URL length limit of 2083 is hit
429Too Many Requests –Throttled API response, as a result of rate-limiting feature
500 Internal Server Error
501 Not Implemented – A requested method/operation is not implemented by service
503 Service Unavailable (with details if in debug mode) - In case of service based errors
• Repeated calls to the same resource must
recreate entities
• E.g. Repeatedly calling PUT /players/1a should
just update the record
• PATCH special case
• HypermediaAsThe Engine Of Application
State
• Sticky links in API responses
• Includes schema details
• Provides navigational elements (links) to
entities used in an API response
• {
"links":[
{
"href":"<baseURL>/players/1a",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":{
"id":"1a",
"name":"A B",
"country_code":"US",
"game_id":"1g"
}
}
• Open Data Framework (odata.org)
• Standard, predictable method to query
• SQL-like syntax in HTTP URLs
• Works atop RESTful GET endpoints
• Reduces cognitive dissonance in developers
• Server and client side libraries exist (Olingo for
Java,ASP.NET in .NET, and others)
• $select - Filter the list of attributes from an instance (SELECT)
• $filter - Expressions to filter list of records from a collection
(WHERE)
• $top - Number of records to retrieve (FETCH orTOP or LIMIT)
• $offset - Skip to this record number (OFFSET)
• $expand - Expand body of an aggregation/reference entity
(similar to adding a JOIN)
• $orderby - Sort the collections based on given column
name(s) (ORDER BY)
• $count - Return only the count of records in case of a
collections call. (COUNT)
• $select - Filter the list of attributes from an instance (SELECT)]
GET /players?$select=name
{
"links":[
{
"href":"<baseURL>/players?$select=name",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":[
{
"name":"A B"
}
]
}
• $filter - Expressions to filter list of records from a collection (WHERE)
GET /players?$filter=name eq ‘A B’&$select=id,name
{
"links":[
{
"href":"<baseURL>/players?$filter=name eq ‘A B’&$select=id,name ",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":[
{
"id":"1a",
"name":"A B"
}
]
}
• $top - Number of records to retrieve (FETCH orTOP or LIMIT)
• $offset - Skip to this record number (OFFSET)
• GET /players?$top=1&$offset=2 (Skips two records and takes 1)
{
"links":[
{
"href":"<baseURL> /players?$top=1&$offset=2",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":[
{
"id":"1a",
"name":"A B",
"country_code":"US",
"game_id":"1g"
}
]
}
• $expand - Expand body of an aggregation/reference entity (similar to adding a JOIN)
• GET /players/1a?$expand=game
{
"links":[
{
"href":"<baseURL>/players/1a?$expand=game",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":
{
"id":"1a",
"name":"A B",
"country_code":"US",
"game":{
"id":"1g",
"name":"Contra"
}
}
}
• $expand - Expand body of an aggregation/reference entity
• GET /players?$orderby=name
{
"links":[
{
"href":"<baseURL>/players?$orderby=name ",
"schema":"<baseURL>/schemas/$players",
"rel":"players | self"
},
{
"href":"<baseURL>/games/1g",
"schema":"<baseURL>/schemas/$games",
"rel":"games"
}
],
"data":[
{
"id":"1a",
"name":"A B",
"country_code":"US",
"game_id":"1g"
}
}
]
}
• Consider this in C#:
players.Any(p => p.address.city ==
"Foster City" &&
p.validateTrophies()).ToList<Player>();
• To Lambda expression in ODATA
/players?$filter=players/any(p:p/address/
city eq 'Foster City' and
p.validateTrophies())
{
"event" : "player.created",
"for": "<userId>",
"state": "active | inactive",
"description" : "webhook to receive details ",
"callback" : {
"url" : "https://clienturi/statusupdater",
"symkey" : ”a shared secret",
"access-token": "some access token for inbound auth",
"retries" : 5
}
}
• Use RESTful standards
• Use ODATA for predictable
retrieval
• Use appropriate status codes
• Make sure to account for
idempotency and concurrency

More Related Content

PPTX
apidays LIVE LONDON - Data Retrieval via APIs - Showdown of GraphQL vs ODATA ...
PDF
Using Apache Solr
PDF
Solr's Search Relevancy (Understand Solr's query debug)
PDF
it's just search
PDF
Data Exploration with Elasticsearch
PDF
Drupal 7 database api
PPT
eZ Publish Cluster Unleashed
PDF
Configuration resources
apidays LIVE LONDON - Data Retrieval via APIs - Showdown of GraphQL vs ODATA ...
Using Apache Solr
Solr's Search Relevancy (Understand Solr's query debug)
it's just search
Data Exploration with Elasticsearch
Drupal 7 database api
eZ Publish Cluster Unleashed
Configuration resources

What's hot (20)

PDF
Fun with Python
PDF
Solr Masterclass Bangkok, June 2014
PPTX
API Design Antipatterns - APICon SF
PPT
Introduction to Google API - Focusky
PDF
Great+Seo+Cheatsheet
PDF
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
KEY
Routing 1, Season 1
PDF
Layouts and Rendering in Rails, Season 2
PPTX
Android Lab Test : Reading the foot file list (english)
PPTX
Oozie or Easy: Managing Hadoop Workloads the EASY Way
PPTX
Rebuilding Solr 6 examples - layer by layer (LuceneSolrRevolution 2016)
PDF
[2B1]검색엔진의 패러다임 전환
PPTX
Drupal 8. Search API. Facets. Customize / combine facets
PDF
Getting Creative with WordPress Queries
PDF
[2C6]SQLite DB 의 입출력 특성분석 : Android 와 Tizen 사례
PPT
Web Scraping with PHP
PPTX
Puppet Camp DC: Puppet for Everybody
ZIP
What's new in the Drupal 7 API?
PPTX
Dangerous google dorks
PDF
NoSQL & MongoDB
Fun with Python
Solr Masterclass Bangkok, June 2014
API Design Antipatterns - APICon SF
Introduction to Google API - Focusky
Great+Seo+Cheatsheet
Tutorial, Part 3: SharePoint 101: Jump-Starting the Developer by Rob Windsor ...
Routing 1, Season 1
Layouts and Rendering in Rails, Season 2
Android Lab Test : Reading the foot file list (english)
Oozie or Easy: Managing Hadoop Workloads the EASY Way
Rebuilding Solr 6 examples - layer by layer (LuceneSolrRevolution 2016)
[2B1]검색엔진의 패러다임 전환
Drupal 8. Search API. Facets. Customize / combine facets
Getting Creative with WordPress Queries
[2C6]SQLite DB 의 입출력 특성분석 : Android 와 Tizen 사례
Web Scraping with PHP
Puppet Camp DC: Puppet for Everybody
What's new in the Drupal 7 API?
Dangerous google dorks
NoSQL & MongoDB
Ad

Similar to Api design and usability (20)

KEY
PPT
RESTful SOA - 中科院暑期讲座
PPTX
Pragmatic REST APIs
PPT
PHP Server side restful API - linkedin
PDF
The never-ending REST API design debate
PPTX
REST Api Tips and Tricks
PDF
REST easy with API Platform
PPTX
REST Methodologies
KEY
Designing a RESTful web service
PPTX
Rest Essentials
PDF
Ws rest
ODP
Intravert Server side processing for Cassandra
ODP
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
PDF
RefCard RESTful API Design
PDF
Apidays New York 2024 - Build a terrible API for people you hate by Jim Benne...
ODP
NEPHP '13: Pragmatic API Development
PDF
Api's and ember js
PPSX
Rest api standards and best practices
PPTX
A Deep Dive into RESTful API Design Part 2
PDF
RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK - Nicola Iarocci - Co...
RESTful SOA - 中科院暑期讲座
Pragmatic REST APIs
PHP Server side restful API - linkedin
The never-ending REST API design debate
REST Api Tips and Tricks
REST easy with API Platform
REST Methodologies
Designing a RESTful web service
Rest Essentials
Ws rest
Intravert Server side processing for Cassandra
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
RefCard RESTful API Design
Apidays New York 2024 - Build a terrible API for people you hate by Jim Benne...
NEPHP '13: Pragmatic API Development
Api's and ember js
Rest api standards and best practices
A Deep Dive into RESTful API Design Part 2
RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK - Nicola Iarocci - Co...
Ad

Recently uploaded (20)

PDF
Encapsulation_ Review paper, used for researhc scholars
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Approach and Philosophy of On baking technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Electronic commerce courselecture one. Pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
Machine Learning_overview_presentation.pptx
PPT
Teaching material agriculture food technology
PPTX
Spectroscopy.pptx food analysis technology
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
Encapsulation_ Review paper, used for researhc scholars
“AI and Expert System Decision Support & Business Intelligence Systems”
Approach and Philosophy of On baking technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
A comparative analysis of optical character recognition models for extracting...
Spectral efficient network and resource selection model in 5G networks
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Electronic commerce courselecture one. Pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Machine Learning_overview_presentation.pptx
Teaching material agriculture food technology
Spectroscopy.pptx food analysis technology
Per capita expenditure prediction using model stacking based on satellite ima...
Building Integrated photovoltaic BIPV_UPV.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Network Security Unit 5.pdf for BCA BBA.
20250228 LYD VKU AI Blended-Learning.pptx

Api design and usability

  • 3. • Be REST Assured (RESTfulness) • HATEOAS • ODATA for Data Retrieval • Webhooks / Callbacks
  • 4. • Resources / Entities Depiction • HTTPVerb Usage • Entity Relationships • Status Codes • Idempotency
  • 5. • Pluralized nouns for entities /users • Actions using HTTP methods GET /users • Instances vs Collections GET /users (returns a collection) GET /users/1a (returns an instance)
  • 6. • GET : Retrieve an instance or collection. • POST : Creates an entity record. • PUT : Updates a wholesome entity given its ID. • DELETE: Removes an entity given its ID • PATCH: Partially updates an entity given its ID • OPTIONS: Returns list of HTTP methods available for an entity
  • 7. • POST /players { "name":"A B", "country_code":"US", "phone":"000 000 0000" } Response 201 Created { "id":"1a", "name":"A B", "country_code":"US", "phone":"000 000 0000" }
  • 8. • POST /players/1a/trophies { "game":"Mario", "trophy_name":"Champion" } Response: 201 Created { "id":"1t", "game":"Mario", "trophy_name":"Champion" }
  • 9. • GET /players/1a { ”id":”1a", "name":"A B", "country_code":"US", "phone":"000 000 0000", "trophies":[ { "id":"1t", "game":"Mario", "trophy_name":"Champion" }, { "id":"2t", "game":"Contra", "trophy_name":"Champion" } ] }
  • 10. 200 OK – ResponseOK. Should be used in GET (or PUT calls containing modified entity) 201 Created – Returned by a synchronous POST call creates an entity. 202 Accepted – Result of an long running operation by a POST call. 204 No Content – Result of a synchronous operation by a DELETE or PUT/PATCH 304 Not Modified – A cached response is returned 400 Bad Request – A malformed JSON request is sent 401 Unauthorized – API user is not authenticated. Bad credentials. 403 Forbidden – API user is not authorized. User roles don’t allow invoking an endpoint 409 Conflict – A race condition is found (validation of updated/modified timestamp failed) 404 Not Found – Record for provided ID is not found, in case of GET, DELETE, PUT, PATCH 408 RequestTimeout – Server couldn’t process the request in a specified time limit 414 URIToo Long – When the URL length limit of 2083 is hit 429Too Many Requests –Throttled API response, as a result of rate-limiting feature 500 Internal Server Error 501 Not Implemented – A requested method/operation is not implemented by service 503 Service Unavailable (with details if in debug mode) - In case of service based errors
  • 11. • Repeated calls to the same resource must recreate entities • E.g. Repeatedly calling PUT /players/1a should just update the record • PATCH special case
  • 12. • HypermediaAsThe Engine Of Application State • Sticky links in API responses • Includes schema details • Provides navigational elements (links) to entities used in an API response
  • 13. • { "links":[ { "href":"<baseURL>/players/1a", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data":{ "id":"1a", "name":"A B", "country_code":"US", "game_id":"1g" } }
  • 14. • Open Data Framework (odata.org) • Standard, predictable method to query • SQL-like syntax in HTTP URLs • Works atop RESTful GET endpoints • Reduces cognitive dissonance in developers • Server and client side libraries exist (Olingo for Java,ASP.NET in .NET, and others)
  • 15. • $select - Filter the list of attributes from an instance (SELECT) • $filter - Expressions to filter list of records from a collection (WHERE) • $top - Number of records to retrieve (FETCH orTOP or LIMIT) • $offset - Skip to this record number (OFFSET) • $expand - Expand body of an aggregation/reference entity (similar to adding a JOIN) • $orderby - Sort the collections based on given column name(s) (ORDER BY) • $count - Return only the count of records in case of a collections call. (COUNT)
  • 16. • $select - Filter the list of attributes from an instance (SELECT)] GET /players?$select=name { "links":[ { "href":"<baseURL>/players?$select=name", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data":[ { "name":"A B" } ] }
  • 17. • $filter - Expressions to filter list of records from a collection (WHERE) GET /players?$filter=name eq ‘A B’&$select=id,name { "links":[ { "href":"<baseURL>/players?$filter=name eq ‘A B’&$select=id,name ", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data":[ { "id":"1a", "name":"A B" } ] }
  • 18. • $top - Number of records to retrieve (FETCH orTOP or LIMIT) • $offset - Skip to this record number (OFFSET) • GET /players?$top=1&$offset=2 (Skips two records and takes 1) { "links":[ { "href":"<baseURL> /players?$top=1&$offset=2", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data":[ { "id":"1a", "name":"A B", "country_code":"US", "game_id":"1g" } ] }
  • 19. • $expand - Expand body of an aggregation/reference entity (similar to adding a JOIN) • GET /players/1a?$expand=game { "links":[ { "href":"<baseURL>/players/1a?$expand=game", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data": { "id":"1a", "name":"A B", "country_code":"US", "game":{ "id":"1g", "name":"Contra" } } }
  • 20. • $expand - Expand body of an aggregation/reference entity • GET /players?$orderby=name { "links":[ { "href":"<baseURL>/players?$orderby=name ", "schema":"<baseURL>/schemas/$players", "rel":"players | self" }, { "href":"<baseURL>/games/1g", "schema":"<baseURL>/schemas/$games", "rel":"games" } ], "data":[ { "id":"1a", "name":"A B", "country_code":"US", "game_id":"1g" } } ] }
  • 21. • Consider this in C#: players.Any(p => p.address.city == "Foster City" && p.validateTrophies()).ToList<Player>(); • To Lambda expression in ODATA /players?$filter=players/any(p:p/address/ city eq 'Foster City' and p.validateTrophies())
  • 22. { "event" : "player.created", "for": "<userId>", "state": "active | inactive", "description" : "webhook to receive details ", "callback" : { "url" : "https://clienturi/statusupdater", "symkey" : ”a shared secret", "access-token": "some access token for inbound auth", "retries" : 5 } }
  • 23. • Use RESTful standards • Use ODATA for predictable retrieval • Use appropriate status codes • Make sure to account for idempotency and concurrency