...
- Nice: Do not expose database IDs where possible (Must for external APIs, per dev ops)
- Must: edX resource identifiers
Users should be referenced by username.
- Courses runs should be referenced via course run keys (eg. course-v1:edX+BlendedX+1T2018)
- Catalog courses should be referenced via a catalog UUID.
- Course blocks should be referenced via usage keys (eg. block-v1:org+course+run+type@sequential+block@2aa6fc9d8278)
- Explicit Filters
- Model system resource URL schemes as if all resources are available to all users
- Include all necessary filters in the URL such that any user could theoretically access the resource
Separate filtering and authorization – ie, do not return different resource representations via the same URL based on the requesting userAnchor username username Example 1: Choose "/profiles/john_harvard" over "/profile"
Example 2: Choose "/courses?username=john_harvard" over "/courses"
- See relevant conversation here for more context.
Remember, it's entirely possible that "/profiles/john_harvard" or "/courses?username=john_harvard" could be requested by the "administrator" user
- Several benefits exist from an explicit filtering approach:
- Ensures resources/results are individually-addressable
- Enables discovery/sharing of resources, among other potential uses
- Resource filtering mechanisms can be modified without impacting authorization mechanisms
- Intermediate network gear can cache resource representations to improve performance (for open/unprotected resources)
- Composite Resource (with multiple dimensions)
- If an endpoint represents a relationship among multiple dimensions, the dimensions can be specified in the following ways:
- As filter parameters:
/api/enrollments/v1/enrollments/?user={username}&course={course_id}
- As comma-delimited resource keys in the URL:
/api/enrollments/v1/enrollments/{username},{course_id}
- As a UUIDs to uniquely identify the relationship:
/api/enrollments/v1/enrollments/{enrollment_id}
...
HTTP status codes - Use the appropriate value amongst the following (or document in the code why an exception is needed)
- 200 - OK
- 201 - Created
- 204 - OK, no content returned (use for PATCH)
- 304 - Not Modified
- 400 - Bad Request
- 401 - Unauthorized (for unauthenticated users)
- 403 - Forbidden (for authenticated users who do not have the right permissions)
- 404 - Not Found
- 415 - Unsupported Media Type (used for PATCH if implementation is "merge patch" algorithm, and caller did not specify "application/merge-patch+json" content_type).
- 500 - Internal Server Error
- Prevent information leakage
Must: Use 404 instead of 403 when the actual existence would be leaking information that we don't want - Dave O.
Error Description
Must: Be verbose and use plain language descriptions.
- Must: Use i18n for user facing messages ("user_message" in example below)
Nice: Add as many hints as your API team can think of about what's causing an error.
Nice: Add a link in your description to more information, like Twilio does.
Error format:
developer_message (no i18n)
user_message(optional, but if provided, i18n as the expectation is that this may surface in a UI)
field_errors (if applicable)
error_code (for example: see has_access interface design) Include description in your REST API Docs.
Code Block { "error_code": "course_not_started" # a short string that the client can rely upon for handling different errors "developer_message" : "Verbose, plain language description of the problem for the app developer with hints about how to fix it.", "user_message":"Pass this message on to the app user if needed.", "field_errors": { "foo": { "developer_message": "", "user_message": "" } } }
...