Creating Solid APIs

Creating Solid APIs

Presented at DjangoCon Europe 2018

Creating APIs that other developers love to use isn't trivial. I'll share some tips and best practices.

895ac7b84a280f686b70e2a70a8f5cd9?s=128

Rivo Laks

May 23, 2018
Tweet

Transcript

  1. Creating Solid APIs DjangoCon Europe 2018 ⋅Rivo Laks 2018-05-23

  2. Background

  3. What is an API?

  4. What is an API? application programming interface

  5. What is an API? application programming interface application programmer interface

  6. What is an API? application programming interface application programmer interface

    API is user interface for developers
  7. What Makes an API Good?

  8. What Makes an API Good? Documentation

  9. What Makes an API Good? Documentation Familiarity

  10. What Makes an API Good? Documentation Familiarity Lack of friction

  11. Documentation Often overlooked

  12. Documentation Often overlooked Gives the rst impression

  13. Documentation Often overlooked Gives the rst impression The e ort

    is worth it!
  14. Creating Awesome Docs

  15. What Should Go In There?

  16. What Should Go In There? How do I access it?

  17. What Should Go In There? How do I access it?

    Do I need developer account?
  18. What Should Go In There? How do I access it?

    Do I need developer account? Root URL, etc
  19. What Should Go In There? How do I access it?

    Do I need developer account? Root URL, etc Authentication info
  20. What Should Go In There? General encodings, formats, etc

  21. What Should Go In There? General encodings, formats, etc Pagination,

    versioning, etc
  22. What Should Go In There? General encodings, formats, etc Pagination,

    versioning, etc Common errors
  23. What Should Go In There? General encodings, formats, etc Pagination,

    versioning, etc Common errors Code for getting started
  24. The Endpoints

  25. The Endpoints URL & operations

  26. The Endpoints URL & operations Request/response data

  27. The Endpoints URL & operations Request/response data Optional parameters

  28. The Endpoints URL & operations Request/response data Optional parameters Permissions

    etc
  29. Keep it Fresh!

  30. Keep it Fresh! Obsolete docs are the worst

  31. Keep it Fresh! Obsolete docs are the worst Always autogenerate!

  32. Keep it Fresh! Obsolete docs are the worst Always autogenerate!

    Usually code » schema » docs
  33. Schema & Autogeneration

  34. Schema & Autogeneration OpenAPI, Swagger, etc

  35. Schema & Autogeneration OpenAPI, Swagger, etc Use your tools

  36. Schema & Autogeneration OpenAPI, Swagger, etc Use your tools Combine

    docs & code examples
  37. Schema & Autogeneration OpenAPI, Swagger, etc Use your tools Combine

    docs & code examples Client libs autogeneration
  38. Standardize!

  39. JSON API http://jsonapi.org/ one potential standard to use

  40. JSON API http://jsonapi.org/ one potential standard to use GraphQL is

    another option
  41. Standardize Structure

  42. Standardize Structure Responses have predictable, familiar structure

  43. GET https://example.com/api/v1/projects { "links": { "next": "https://example.com/api/v1/projects?cursor=cD0yMDE4L", "prev": null },

    "data": [...], "included": [...] }
  44. "data": [ { "type": "project", "id": "289", "links": { "self":

    "https://example.com/api/v1/projects/289" }, "attributes": { "created": "2018-04-28T22:52:08.690486Z", "name": "Allison-Patterson", "description": "aggregate collaborative models" }, "relationships": {...} }, ... ],
  45. "data": [{ ... "relationships": { "created_by": { "data": { "type":

    "user", "id": "199" } }, "epics": { "data": [ { "type": "epic", "id": "3101" } ], } } }, ... ],
  46. "included": [ { "type": "epic", "id": "3101", "attributes": { "created":

    "2018-04-28T22:50:45.885691Z", "name": "Ergonomic background extranet" }, "links": { "self": "https://example.com/api/v1/epics/3101" } }, { "type": "user", "id": "199", "attributes": {...} } ]
  47. Impressions?

  48. Flexibility Con gurable elds: GET https://example.com/api/v1/projects GET https://example.com/api/v1/projects \ ?included=comments

    GET https://example.com/api/v1/projects \ ?included=comments&fields[project]=name,comments
  49. Pagination List responses have next / prev links { "links":

    { "next": "https://example.com/api/v1/projects?cursor=cD0yMDE4L", "prev": null }, "data": [...], }
  50. Pagination List responses have next / prev links { "links":

    { "next": "https://example.com/api/v1/projects?cursor=cD0yMDE4L", "prev": null }, "data": [...], } Cursor-base pagination FTW (but YMMV)
  51. There is More ... Filtering Ordering

  52. Errors

  53. Errors POST https://example.com/api/v1/projects { "errors": [ { "title": "Invalid Attribute",

    "detail": "Name must contain at least three letters.", "source": { "pointer": "/data/attributes/name" }, "status": "422" } ] }
  54. Special Cases For when you have LOTS of data

  55. Special Cases For when you have LOTS of data out-of-band

    approach
  56. GET https://example.com/api/v1/datasets/123 { "data": { "type": "dataset", "id": "123", "attributes":

    { "name": "CIFAR10 dataset", }, "links": { "data_tgz": "https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz", "self": "https://example.com/api/v1/datasets/123" } } }
  57. Standardization Matters the speci c standard isn't that important GraphQL,

    etc are also good options
  58. Authentication & Authorization

  59. Token Authentication Clients send HTTP header, ala Authorization: Token 9944b09199c62bcf9418

  60. OAuth 2.0

  61. OAuth 2.0 For creating platforms

  62. OAuth 2.0 For creating platforms Complex, but solves many issues

  63. OAuth 2.0 For creating platforms Complex, but solves many issues

    Many packages, e.g. Django OAuth Toolkit, OAuthLib
  64. Versioning

  65. Versioning Schemes

  66. Versioning Schemes AcceptHeaderVersioning (DRF) GET /projects HTTP/1.0 Accept: application/json; version=1.0

  67. Versioning Schemes AcceptHeaderVersioning (DRF) GET /projects HTTP/1.0 Accept: application/json; version=1.0

    URLPathVersioning (DRF) GET /v1/projects HTTP/1.0 Accept: application/json
  68. Versioning Schemes Cont. Integers ( v1 ) vs dates (

    2018-05-23 )?
  69. Versioning Schemes Cont. Integers ( v1 ) vs dates (

    2018-05-23 )? Dates are less emotional
  70. Versioning Schemes Cont. Integers ( v1 ) vs dates (

    2018-05-23 )? Dates are less emotional Make upgrades easy
  71. Version Transformers

  72. Version Transformers » » Requests into newer version » »

    Core code is for latest version « « Responses into older version « «
  73. Version Transformers » » Requests into newer version » »

    Core code is for latest version « « Responses into older version « « Won't work for big, breaking changes
  74. tg-apicore

  75. Thorgate API Core pip install tg-apicore Addon for Django REST

    Framework
  76. Thorgate API Core pip install tg-apicore Addon for Django REST

    Framework Documentation generation Pre-con gured Viewset/serializer utils
  77. Client's Perspective

  78. The Scenario Let's try speech recognition...

  79. The Scenario Let's try speech recognition... ... using AWS and

    GCP
  80. Getting Started Documentation

  81. Getting Started Documentation Quite easy to nd A bit overwhelming

  82. Getting Started Documentation Quite easy to nd A bit overwhelming

    Code examples
  83. Comprehensive Clients Install Python client GCP: google-cloud package AWS: boto3

    package
  84. Comprehensive Clients Install Python client GCP: google-cloud package AWS: boto3

    package Authenticate
  85. Comprehensive Clients Install Python client GCP: google-cloud package AWS: boto3

    package Authenticate Thorough docs
  86. Amazon import boto3 client = boto3.client('transcribe') response = client.start_transcription_job(...)

  87. Amazon import boto3 client = boto3.client('transcribe') response = client.start_transcription_job(...) Google

    from google.cloud import speech client = speech.SpeechClient() results = client.recognize(...)
  88. In Summary Invest in documentation Embrace standards (e.g. JSON API)

    Use automation Reduce friction
  89. Thanks! Rivo Laks ⋅ @rivolaks ⋅ rivolaks.com Lead Engineer at

    Thorgate ⋅ thorgate.eu API framework for Django/DRF ⋅ tg-apicore (WIP)