Skip to content

API General

Michael Bryant edited this page Feb 19, 2020 · 2 revisions

General API Outline

This document outlines the general patterns that all API endpoints will follow, regardless of the resource returned.

Terminology

  • Admin: A User with administrative (superuser) capabilities on the Server application.
  • Collection: An endpoint representing a place to interact with multiple Resources at once, or create a new Resource.
  • Placeholder: In the API path, a word beginning with a colon (:) is a placeholder for some other value.
  • Resource: An JSON object returned by an API call, containing all of the relevant information related to the data object it represents. References to other Resources should be restricted to Resource Summaries.
  • Resource Summary: A stripped-down JSON representation of a resource with a link to retrieve the full information. It should contain only enough information to display a summary of the Resource.
  • Resource Type: The category/data type that multiple Resources fall under, e.g. users, items, spells.
  • System: Tavern's server application.
  • User: A person with an account on the System or the data related to that account.

HTTP Methods

As a central note: some HTTP methods do not have a body in the request and/or the response. Check the Mozilla Developer Network for more information.

JSON Responses

All responses from the server that contain JSON (so basically all of them) must include the header Content-Type: application/json; charset=UTF-8. This indicates to clients that the response should be parsed as UTF-8-encoded JSON data.

Request Requirements

Headers

  • An Accept header indicating which content type(s) the client will accept. The server will use this to choose which content type to respond with.
  • An Authorization header to authenticate requests.
  • A Cache-Control header (Caching on MDN)
  • A Content-Encoding header indicating how the request was compressed, if at all.
  • A Content-Length header indicating the length of the request body, in bytes.
  • A Content-Type header of application/x-www-form-urlencoded or multipart/form-data on PUT, POST, and PATCH requests.
  • A Digest header containing a checksum of the request body.
  • An If-None-Match header on cacheable requests so the server can determine if the cache is still valid (using a received ETag value).
  • An If-Unmodified-Since header to ensure that a Resource has not been modified since a client started editing it.

Authorization

All requests requiring authorization must include authentication using HTTP Basic. Authentication using the Basic method operates as follows:

  1. Username and password are combined with a colon: username:password. The username must not contain a colon; the password may contain one or more.
  2. The combined string is base64-encoded: dXNlcm5hbWU6cGFzc3dvcmQ=.
  3. The Authorization header is set on the request: Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=.

Response Requirements

Headers

  • A Cache-Control header (Caching on MDN)
  • A Content-Encoding header indicating how the response was compressed, if at all.
  • A Content-Length header indicating the length of the response body, in bytes.
  • A Content-Type header of application/json on all responses (until support for XML, etc. is added)
  • A Digest header containing a checksum of the response body.
  • An ETag header on cacheable responses for the client to store with the cache so the server can later determine if the cache is still valid.
  • A Retry-After header to tell a rate-limited client when they are allowed to try connecting again.
  • A Server header indicating that our Tavern server is the server being used (avoid version information to make attacks more difficult).
  • A WWW-Authenticate header indicating how to correctly authenticate with the server, used only with 401 Unauthorized responses (see not_authenticated error).

Resource Links

Every Resource returned from the server should have a links attribute, which indicates the links related to the given resource. These links can be to related resources (e.g. a user's characters) or to actions that a user may perform (for dynamically determining which UI elements to enable/disable). It should look something like this:

{
  "links": [
    {
      "href": "/:resources/:id",
      "rel" : "character",
      "method": "GET",
      
    }
  ]
}

Collections

  • /:resources: An endpoint for a collection of a kind of resource, e.g. /users, /items.

    • OPTIONS: GET, POST, PUT, PATCH, DELETE
    • GET: Return a list of Resource Summaries of the given kind.
      • Authorization: Any User.
      • Request: No body. May have a query string containing the common filtering queries.
      • Response: A JSON array of Resource Summaries.
        • Status: 200 OK
        • Body: Note that the only information in the example below expected to show up in a given resource is id and links.
          [
            {
              "id": "e637cbcc-12d8-4024-bc47-fa4268b4ec5b",
              "name": "Example resource",
              "type": "summary",
              "links": [
                {
          		"href": "/resources/e637cbcc-12d8-4024-bc47-fa4268b4ec5b",
          		"rel": "self",
          		"method": "GET"
                }
              ]
            }
          ]
    • POST: Create a new resource of the given type.
      • Authorization: Any User.
      • Request: Should contain the relevant information for creating a new Resource. See details for each resource type for what information is required.
        • Headers:
          • Content-Type: application/x-www-form-urlencoded if only text, multipart/form-data; boundary=[BOUNDARY] if contains binary data.
        • Body:
          • Appropriately formatted to contain form data. See Mozilla Developer Network for above content types more info.
      • Response: Contains the newly created resource.
        • Errors: invalid_request, not_authenticated, not_authorized, rate_limited.
        • Success:
          • Status code: 201 Created
          • Headers:
            • Location: A link to the newly created resource, e.g. /resources/e637cbcc-12d8-4024-bc47-fa4268b4ec5b.
          • Body: The same contents as if a GET request were made to the location in the Location header.
    • PUT: (!MVP) Batch update Resources under this collection.
    • PATCH: (!MVP) Batch partial update Resources under this collection.
    • DELETE: (!MVP) Batch delete Resources under this collection.
  • /:resources/:id/:other: An endpoint for a collection under a specific Resource (e.g. a specific user's characters)

    • OPTIONS: GET, (POST, PUT, PATCH, DELETE)?
      • (TODO) Should new Resources be created e.g. at /users/:id/characters or /characters? Should probably avoid the duplication of using both.
      • Possible idea: /items is all items the User can access, while /users/:id/items is all items the user created.
    • Requests/responses per method should look the same as above, with the additional possibility of a resource_not_found error.

Resources

  • /:resources/:id: An endpoint representing one specific Resource.

    • OPTIONS: GET, PUT, PATCH, DELETE
    • POST: Is not allowed and should respond with a method_not_allowed error.
    • GET: Retrieves the full information about the Resource and returns it to the client.
      • Authorization: Admins, the User who created the Resource, possibly any User.
      • Request: No body.
      • Response:
        • Errors: not_authenticated, not_authorized, rate_limited, resource_not_found.
        • Success:
          • Status code: 200 OK
          • Body:
            {
              "id": "e637cbcc-12d8-4024-bc47-fa4268b4ec5b",
              // Other information
              "links": [
                {
              	"href": "/resources/e637cbcc-12d8-4024-bc47-fa4268b4ec5b",
              	"rel": "self",
              	"method": "GET"
                }
              ]
            }
    • PUT: Updates the existing Resource.
      • Authorization: Admins or the User who created the Resource
      • Request: Same requirements as POST for /:resources.
      • Response:
        • Headers: None?
        • Status code: 204 No Content
        • Body: None
    • PATCH:
      • Authorization: Admins or the User who created the Resource
      • Request: Same as PUT, but some fields may be missing
      • Response: Same as PUT
    • DELETE:
      • Authorization: Admins or the User who created the Resource
      • Request: No body.
      • Response:
        • Status code: 204 No Content
        • Body: None
  • /:resources/:id/:other/:id: An endpoint for a Resource in a collection under a different Resource (e.g. a specific user's specific character)

    • OPTIONS: (GET, PUT, PATCH, DELETE)?
      • (TODO) Similar to /:resources/:id/:other, should these nested resources be found under the top resource, or in their own top-level collection? Maybe top-level is read-only/Admin edit only, and nested is for editing?
    • Requests/responses per method should look the same as above, with the additional possibility of an extra resource_not_found error.