Optional Fields and API Versioning
While adding a feature to the Discussion API, questions arose regarding the best way to handle optional fields, as well as handling API versioning.
For the Discussion API, we wish to add profile images for users to certain endpoints, but to add them optionally for performance reasons.
Summary
Of the options listed below, we have decided to implement option #4.
Discussion API Optional Field
The Discussion API responses are currently flat:
{ ... "group_name": null, "author": "example-user", "created_at": "2015-04-09T17:31:56Z", ... }
Ideally, the profile image would be added under the author (as part of a v2 breaking change), like the following:
{ ... "author": { "username": "example-user", "profile": { "image": { "raw": "http://...", "small": "http://...", }, }, }, ... }
Alternatives to Expanding Objects
The current convention for expanding objects using "?expand=" doesn't seem granular enough because we don't want to include all profile information, at least at this time.
What would be the best parameter option:
- ?requested_fields=profile_image
- The "requested_fields" parameter is used by the Course Blocks API.
- The right-hand side would be a way to add profile images for all users.
- ?requested_fields=author_profile_image,endorse_profile_image
- Same as above, but force each individual field to be listed.
- ?[include_]profile_image=endorsed,author,last-modified
A profile imagine unique query param.
- Other?
API Evolution and Versioning
The next question is around the best way to evolve our APIs and determine when and if we should make backward incompatible change.
Option 1
A backward compatible compromise that moves us toward a more ideal response to avoid bumping versions.
{ ... "author": "example-user", "author_details": { "profile": { "image": { "raw": "http://...", "small": "http://...", }, }, }, ... }
Option 2
Introduce v2 of the API and make a backward incompatible change.
{ ... "author": { "username": "example-user", "profile": { "image": { "raw": "http://...", "small": "http://...", }, }, }, ... }
This option has additional questions related to API versioning:
- Can and should we bump the version for small changes without forcing the team to review and update all other possible backward compatible changes at the same time? What are alternatives toward keeping the scope small when attempting to keeping our APIs clean?
- Do we need to determine when, how and if we retire old versions, or can that be a concern for the future?
Option 3
Keep a semi-flat structure and add profile_images to the top-level. The profile_images itself would not be flat, and would allow for an image per user, keyed by user id.
{ ... "author": "example-user", ... "profile_images": { "example-user": { ... }, "username2": { ... }, "username3": { ... }, } }
Option 4
Add a structure for user details keyed by user id.
{ ... "author": "example-user", ... "users": { "example-user": { "profile": { "image": { "raw": "http://...", "small": "http://...", }, }, }, "username2": { ... }, "username3": { ... }, } }