Upgrade to Pro — share decks privately, control downloads, hide ads and more …

API Standards 2.0

API Standards 2.0

We’re all familiar with things like HTTP codes and content types, but there’s so much more we can do when developing an API to make life easier for consumers. How many times have you used an API only to find out that every endpoint is slightly different – some use `snake_case`, others `camelCase`, sometimes the field is called `id`, sometimes it’s `user_id`. How about pagination? Error responses? What about API documentation?

Trying to standardise on all these things can kill an engineering team. There are so many options out there it’s difficult to know where to start. Come along and learn what works for our team! We’ll cover contentious topics (should the version be in the URL or a header?), lesser-known standards that are great (RFC 7807 springs to mind) and a couple of things that aren’t an issue right up until they’re a really big issue (like pagination).

Michael Heap

October 04, 2018
Tweet

More Decks by Michael Heap

Other Decks in Technology

Transcript

  1. API STANDARDS 2.0

    View full-size slide

  2. HELLO!
    I 'm Michael
    I'm @mheap on Twitter
    I have a favourite Time Zone (DMT)

    View full-size slide

  3. API STANDARDS 2.0

    View full-size slide

  4. API STANDARDS 2.0
    AN OPINIONATED
    GUIDE TO

    View full-size slide

  5. APIs at Nexmo
    6
    REST-like

    View full-size slide

  6. APIs at Nexmo
    7
    Pragmatic
    REST-like

    View full-size slide

  7. APIs at Nexmo
    8
    Pragmatic
    REST-like
    Consumer
    Success

    View full-size slide

  8. API Standards
    9
    Status
    Codes

    View full-size slide

  9. API Standards
    10
    HTTP
    Verbs
    Status
    Codes

    View full-size slide

  10. API Standards
    11
    HTTP
    Verbs
    Status
    Codes
    Nouns,
    not Verbs

    View full-size slide

  11. What we're not going to cover
    ▸ Message formats
    ▸ Rate limiting
    ▸ Content negotiation
    ▸ HTTP headers
    ▸ Hypermedia
    ▸ Resource design
    ▸ Response design
    ▸ RPC endpoints
    ▸ Documentation
    ▸ Asynchronous actions
    ▸ Idempotency
    ▸ Caching
    ▸ API Gateways
    ▸ Security
    ▸ GraphQL
    ▸ Available RFCs
    12

    View full-size slide

  12. 1.
    Errors
    Status Codes, RFC7807 + Extensions
    13

    View full-size slide

  13. 2.
    Versioning
    Header/URL, Versioning Schemes, Deprecation
    14

    View full-size slide

  14. 3.
    Collection Management
    Sorting, Filtering, Searching, Pagination
    15

    View full-size slide

  15. 4.
    URI Design
    Subresources, Action endpoints
    16

    View full-size slide

  16. 1.
    Errors
    Status Codes, RFC7807 + Extensions
    17

    View full-size slide


  17. Errors are easy! People should just
    use status codes

    View full-size slide

  18. 401 Unauthorized
    Error Design
    19

    View full-size slide

  19. 401 Unauthorized
    {
    "error": "No credentials provided"
    }
    Error Design
    20

    View full-size slide

  20. 401 Unauthorized
    {
    "error": "Invalid credentials"
    }
    Error Design
    21

    View full-size slide

  21. 401 Unauthorized
    {
    "error": "Invalid credentials",
    "more_help": "http://example.com/
    auth#invalid-credentials"
    }
    Error Design
    22

    View full-size slide

  22. 401 Unauthorized
    {
    "msg": "Invalid credentials"
    }
    Error Design
    23

    View full-size slide

  23. 401 Unauthorized
    {
    "errorCode": 118118,
    "errorMessage": "Invalid credentials"
    }
    Error Design
    24

    View full-size slide

  24. 401 Unauthorized
    "Invalid credentials"
    Error Design
    25

    View full-size slide

  25. RFC7807
    Type
    A URI
    reference that
    identifies the
    problem type.
    When followed,
    it provides
    human-readable
    documentation
    for the
    problem type
    Title
    A short,
    human-readable
    summary of the
    problem type
    Detail
    A human-
    readable
    explanation
    specific to
    this
    occurrence of
    the problem
    26
    Instance
    A URI
    reference that
    identifies the
    specific
    occurrence of
    the problem

    View full-size slide

  26. RFC7807
    Type
    A URI
    reference that
    identifies the
    problem type.
    When followed,
    it provides
    human-readable
    documentation
    for the
    problem type
    Title
    A short,
    human-readable
    summary of the
    problem type
    Detail
    A human-
    readable
    explanation
    specific to
    this
    occurrence of
    the problem
    27
    Instance
    A URI
    reference that
    identifies the
    specific
    occurrence of
    the problem
    Status
    The HTTP
    status code
    generated by
    the origin
    server for
    this
    occurrence of
    the problem.

    View full-size slide

  27. RFC7807
    Type
    A URI
    reference that
    identifies the
    problem type.
    When followed,
    it provides
    human-readable
    documentation
    for the
    problem type
    Title
    A short,
    human-readable
    summary of the
    problem type
    Detail
    A human-
    readable
    explanation
    specific to
    this
    occurrence of
    the problem
    28
    Instance
    A URI
    reference that
    identifies the
    specific
    occurrence of
    the problem

    View full-size slide

  28. {
    "type": "https://developer.nexmo.com/api-
    errors#unauthorized",
    "title": "Invalid credentials supplied",
    "detail": "You did not provide correct credentials.",
    "instance": "797a8f199c45014ab7b08bfe9cc1c12c"
    }
    RFC7807
    29

    View full-size slide

  29. 403 Forbidden
    {
    "type": "https://example.com/probs/out-of-
    credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but
    that costs 50.",
    "instance": "/account/12345/msgs/abc"
    }
    Extension Members
    30

    View full-size slide

  30. 403 Forbidden
    {
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that
    costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345",
    "/account/67890"]
    }
    Extension Members
    31

    View full-size slide

  31. 400 Bad Request
    {
    "type": "https://developer.nexmo.com/api-errors/account/secret-
    management#validation",
    "title": "Bad Request",
    "detail": "The request failed due to validation errors",
    "invalid_parameters": [
    {
    "name": "secret",
    "reason": "must contain 1 upper case character"
    }
    ],
    "instance": "797a8f199c45014ab7b08bfe9cc1c12c"
    }
    Extension Members
    32

    View full-size slide

  32. 401: No Credentials, Invalid
    Credentials
    403: Feature disabled, Exceeded
    calls-per-second limit
    422: Invalid product specified
    + more!
    Response Library
    33

    View full-size slide


  33. As a consumer of the APIs, this has
    already dramatically reduced the
    amount of code I have to write for
    each endpoint, and I can't wait until
    all endpoints are standardised

    View full-size slide

  34. 2.
    Versioning
    Header/URL, Versioning Schemes, Deprecation
    35

    View full-size slide


  35. The reason to make a real REST API
    is to get evolvability … a "v1" is a
    middle finger to your API customers,
    indicating RPC/HTTP (not REST)
    https://twitter.com/fielding/status/376835835670167552

    View full-size slide

  36. “With a sufficient number of users of an
    interface, it doesn’t matter what you
    promised in the interface contracts, all
    observable behaviors of your class or
    function or whatnot will be depended
    upon by somebody.
    Hyrum's Law

    View full-size slide

  37. Accept: application/vnd.nexmo+json;
    version=3
    URI vs Header
    38

    View full-size slide

  38. Accept: application/vnd.nexmo+json;
    version=3

    X-Nexmo-Version: 3
    URI vs Header
    39

    View full-size slide

  39. Accept: application/vnd.nexmo+json;
    version=3

    X-Nexmo-Version: 3
    https://api.nexmo.com/v3
    URI vs Header
    40

    View full-size slide

  40. https://api.nexmo.com/v1/calls
    Global vs Endpoint versioning
    41

    View full-size slide

  41. https://api.nexmo.com/v1/calls
    https://api.nexmo.com/v1/media
    Global vs Endpoint versioning
    42

    View full-size slide

  42. https://api.nexmo.com/v1/calls
    https://api.nexmo.com/v3/media
    Global vs Endpoint versioning
    43

    View full-size slide

  43. https://api.nexmo.com/v1/calls
    Versioning Scheme
    44

    View full-size slide

  44. https://api.nexmo.com/v1/calls
    https://api.example.com/2010-04-01
    Versioning Scheme
    45

    View full-size slide

  45. https://api.nexmo.com/v1/calls
    https://api.example.com/2010-04-01
    https://api.example.com/1.2.3
    Versioning Scheme
    46

    View full-size slide

  46. https://api.nexmo.com/v3.new-
    feature/calls
    Version Variants
    47

    View full-size slide

  47. Have a deprecation policy. It
    doesn't matter what it is, but be
    consistent.
    Deprecation Policies
    48

    View full-size slide

  48. When the decision has been taken to deprecate an
    API:
    • For beta products the deprecation period must be
    at least 30 days (60 days recommended)
    • For GA products the deprecation period must be at
    least 1 year
    • Warning emails will be sent to the API at regular
    intervals before the deprecation time
    • A guide will be supplied to customers explaining
    how to migrate to the replacement API with the
    initial deprecation notice.
    Deprecation Policies: Nexmo
    49

    View full-size slide

  49. Use the Sunset Header
    Sunset: Sat, 31 Dec 2018 23:59:59
    GMT
    Sunset Header
    50
    https://tools.ietf.org/html/draft-wilde-sunset-header-03

    View full-size slide

  50. Use the Link Header
    Link: shutdown> rel="sunset"
    Link Header
    51

    View full-size slide

  51. 3.
    Collection Management
    Sorting, Filtering, Searching, Pagination
    52

    View full-size slide

  52. GET /users?
    sort_by=email&order_by=asc
    Sorting
    54

    View full-size slide

  53. GET /users?sort_by=email.asc
    Sorting
    55

    View full-size slide

  54. GET /users?sort_by=email.asc
    &sort_by=status.desc
    Sorting
    56

    View full-size slide

  55. GET /users?
    sort_by=email.asc,status.desc
    Sorting
    57

    View full-size slide

  56. GET /users?sort_by=+email,-status
    Sorting
    58

    View full-size slide

  57. GET /users?sort_by=+email,-status
    GET /users?
    sort_by=email.asc,status.desc
    Sorting
    59

    View full-size slide

  58. Filtering
    61
    Discrete data e.g. user role
    Continuous data e.g. subscription
    expiry time

    View full-size slide

  59. Discrete Data
    62
    /users?role=admin
    /orders?shipped=true
    /calls?status=active

    View full-size slide

  60. Discrete Data
    63
    /users?role=admin
    /orders?shipped=true
    /calls?status=active
    403 Forbidden
    /users?is_fbi_informant=true

    View full-size slide

  61. Discrete Data: JSON API
    64
    GET /employees?
    filter[role]=internal&filter[title]=
    senior

    View full-size slide

  62. Discrete Data: JSON API
    65
    GET /employees?
    filter[role]=internal&filter[title]=
    senior
    GET /employees?
    role=internal&title=senior

    View full-size slide

  63. Continuous Data
    66

    View full-size slide

  64. Continuous Data
    67
    GET /orders?
    start_date=2018-01-01&end-
    date=2018=01-31

    View full-size slide

  65. Continuous Data
    68
    GET /orders?
    start_date=2018-01-01&end-
    date=2018=01-31
    GET /orders?
    date[gte]=2018-01-01&date[lte]=2018=
    01-31

    View full-size slide

  66. Industry Standards
    69

    View full-size slide

  67. Industry Standards: SCIM
    70
    filter=userName eq "bjensen"
    filter=name.familyName co "O'Malley"
    filter=userName sw "J"
    filter=urn:ietf:params:scim:schemas:core:
    2.0:User:userName sw "J"
    filter=title pr
    filter=meta.lastModified gt "2011-05-13T04:42:34Z"
    https://tools.ietf.org/html/rfc7644#section-3.4.2.2

    View full-size slide

  68. Searching
    72
    GET /items?q=title:red chair AND
    price:[10 TO 100]

    View full-size slide

  69. Pagination
    73
    Offset based
    Cursor based

    View full-size slide

  70. Pagination: Offset
    74
    GET /calls?page=3&page_size=100

    View full-size slide

  71. Pagination: Cursor
    75
    GET /calls
    GET /calls?
    cursor=2018-01-19T12:33:51
    GET /calls?
    cursor=2018-01-18T03:00:18

    View full-size slide

  72. Pagination: Links
    76
    {
    "_links": {
    "next": {
    "href": "/calls?cursor=9274"
    }
    }
    }
    Link: cursor=9274>; rel="next",

    View full-size slide

  73. 4.
    URI Design
    Subresources, Action endpoints
    77

    View full-size slide

  74. GET /users/1
    Subresources
    78

    View full-size slide

  75. GET /users/1
    GET /users/1/calls
    Subresources
    79

    View full-size slide

  76. GET /users/1
    GET /users/1/calls
    GET /users/1/calls/JSDB-1837A
    Subresources
    80

    View full-size slide

  77. GET /users/1
    GET /users/1/calls
    GET /users/1/calls/JSDB-1837A
    GET /calls/JSDB-1837A
    Subresources
    81

    View full-size slide

  78. GET /users/1
    GET /users/1/calls
    Subresources
    82

    View full-size slide

  79. GET /users/1
    GET /users/1/calls
    GET /calls?user=1
    Subresources
    83

    View full-size slide

  80. GET /users/1
    GET /addresses/33-90210
    GET /users/1/addresses/33-90210
    Subresources
    84

    View full-size slide

  81. GET /users/1
    GET /addresses/33-90210
    GET /users/1/addresses/33-90210
    GET /user_addresses/1-33-90210
    Subresources
    85

    View full-size slide

  82. POST /machines/1/shutdown
    Actions
    86

    View full-size slide

  83. POST /machines/1/shutdown
    POST /machines/1/actions/shutdown
    Actions
    87

    View full-size slide

  84. POST /machines/1/shutdown
    POST /machines/1/actions/shutdown
    POST /machines/1/action:shutdown
    Actions
    88

    View full-size slide

  85. POST /machines/1/shutdown
    POST /machines/1/actions/shutdown
    POST /machines/1/action:shutdown
    POST /machines/1/actions {"type":
    "shutdown"}
    Actions
    89

    View full-size slide

  86. POST /machine-shutdown
    Actions as Resources
    90

    View full-size slide

  87. POST /machine-shutdown
    PUT /article-locks/{article-id}
    DELETE /article-locks/{article-id}
    POST /balance-transfer
    Actions as Resources
    91

    View full-size slide

  88. What we didn't cover
    ▸ Message formats
    ▸ Rate limiting
    ▸ Content negotiation
    ▸ HTTP headers
    ▸ Hypermedia
    ▸ Resource design
    ▸ Response design
    ▸ RPC endpoints
    ▸ Documentation
    ▸ Asynchronous actions
    ▸ Idempotency
    ▸ Caching
    ▸ API Gateways
    ▸ Security
    ▸ GraphQL
    ▸ Available RFCs
    93

    View full-size slide