GlueCon 2013 Notes: Designing a Beautiful REST+JSON API – Les Hazlewood, CTO of Stormpath

2 minute read

Designing a Beautiful REST+JSON API – Les Hazlewood, CTO of Stormpath (@lhazlewood)

  • REST is really hard (for providers)
  • Guidelines and conventions can make it easy
  • Resources are nouns, not verbs
  • Should be course grained, not fine grained (or else the API will grow too large)
  • Don’t do RPC-style (/getUser, /updateUser)
  • HTTP verbs do not have to have a 1:1 correlation with create, read, update, delete
  • GET = Read, DELETE = Delete, HEAD = Headers, no body
  • PUT and POST can BOTH be used for create and update
  • PUT can be used for create if the identifier/location is known by the client (e.g. /applications/clientSpecifiedId)
  • PUT can be used for full replacement update (e.g. PUT /applications/existingId)
    • Must contain the full replacement, making it idempotent on the server (meaning that the same state is the result of multiple calls with the same payload)
  • POST can be used for create on a parent resource (e.g. POST /applications) – return a 201 created and set the Location header to the URL
  • POST can be used as an update (e.g. POST /applications/a1b2c3) – return a 200 OK
  • Media Types provide format specification + parsing rules
    • Request: Accept header
    • Response: Content-Type header
    • application/json
    • application/foo+json
    • application/foo+json;application
    • Very important to nail this (was mentioned early in Fielding’s thesis)
  • Base URLs matter and convey a good (or bad) feeling about the support of your API
  • Versioning – URL or Media-Type (e.g. application/jsonfoo;application&v=1)
    • Media types for versioning isn’t obvious for new developers, but is more correct
  • Resource Format can use the Media-Type (e.g. application/jsonfoo;bar=baz&v=1) but still in flux
  • camelCase to support Javascript naming conventions and for easier consumption
  • Timestamps – ISO 8601 using UTC
  • HREF – distributed hypermedia is paramount!
    • Every accessible resource has a unique URL
    • Replaces IDs (IDs exist, but are opaque)
    • Critical for linking
  • Response Body
    • GET is obvious, but what about POST?
    • Return the representation in the response when feasible
    • Add override (?body=false) for control when payloads may be large or rate limiting based on size
  • Header
    • Accept header, with values in order of preference
  • Resource extensions
    • /applications/a1b2c3.json, .csv, etc. can override accepts
  • Hypermedia is paramount, linking is fundamental to scalability (not to performance, but to data scale and object graphs)
    • Tricky in JSON, easy with XML (XLink)
    • Use ‘href’ to mimic ref attribute in HTML links
  • Reference Expansion (aka Link Expansion or Entity Expansion)
    • Allows clients to control how much data they get back (e.f. x7y8z9?expand=directory)
    • Representation can expand on ‘href’ approach with additional data (or not) and client can handle appropriately
  • Pagination
    • Offset/Limit (e.g. /accounts/x7y8z9/groups?offset=25)
  • Many to Many
    • Mappings should be a resource (GroupMembership for Accounts<–>Groups), allowing for future metadata to the resource
  • Errors
    • As descriptive as possible
    • As much information as possible
    • Developers are your customer
    • Properties recommended: status (409), code (40925), property name, message, developerMessage, moreInfo (URL to docs for error code)
  • Security
    • Avoid server sessions
    • Use standards (OAuth2, Basic auth over SSL only)
  • Longer talk online: http://stormpath.com/blog/designing-rest-json-apis