REST API - Mancario/RheumaApp GitHub Wiki

Note: REST calls can easily be tested with Postman.

Base URL

The base url for all REST calls (for the development system) is https://monitoring-api.monitoring.devops.redrainbow.de/monitoring. All URLs below are relative to this base url.

Authentication & Authorization

All REST calls except login must be authenticated with JWT.

Obtaining a token (login)

POST the user's credentials to /auth/login, where credentials is a JSON document of the following form:

{
    "username": "<a username>",
    "password": "<a password>"
}

The result will be a JSON document with a field success. If success is true, then the token field will be set to the auth token. If success is false, the login was not successful and no token will be returned. Important: If the server returns with a 500 response code (Internal Server Error), the login servers could not be reached. This is usually a temporary issue and the user should be notified accordingly.

The obtained token can then be used to authenticate against the server (see below under "Authentication").

It is important to know that the token has a limited lifetime. In the development environment, we set the lifetime to one week in order to ease manual testing with Postman. However, in production the lifetime of a token will be only in the order of a few minutes. You should therefore regularly refresh the token (see below).

Parsing the token

The token itself is an encoded and signed JSON object that contains login information. You can decode the token programatically with a library such as jwt-decode or use a site like this.

For example, if we decode the token eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDAwMDAwIn0.eoTC9N753V9uzQ7xZOzRZx8CayreeGnioLTR_BBkaQUavEe7dtilvoyV2T1lOdbAaws3s4aJObGwxfv1yTGJQT8uR9aPSUiDp0Ue7vjO5NNAJ759EUBExmh1Gf_Hz_K-0ATOO8GxlurGEmW8wQKSyD88iitOPXMMaiNpBQLN_JiEznzZq7uAXoMGMcimN5mhz4CcjKpJw_Q1v7xXuZzn3QA2uuWoN58Qy9oev4bOoqLPVHswse9I0sbgQ1-X6b4iHKcSFPFax0ntb72nmo39__hoU8p2g44zsYXrEYZo_MquqKNoceyrlAw__Q8k_s4SkBmdmF7L5SHbgEepDy-gng, we get the following result:

{
 "sub": "1000000",
 "jti": "415bd18b-a59f-472c-887c-254e1ba6186d",
 "iat": 1487505107,
 "exp": 1487508707
}

Here iat means "issued at" and exp means expires. Both values are in the standard Unix "seconds since epoch" format, i.e., the token above was issued at Sun, 19 Feb 2017 11:51:47 GMT and expires one hour later.

Authentication

Basically all other requests must then be authenticated. To authenticate, add the Authorization header to the HTTP request as follows:

Authorization: Bearer <token>

where <token> is simply the token obtained before. With Postman, this looks like this;

Testing and refreshing the token

By sending an authenticated POST request to /login/token, you may test validity of the token. If the token is invalid (for example it has expired), the server returns a 401 ("Forbidden") status code (see bottom right):

If the token is still valid, the request is successful and returns a new token with a new expiry time:

REST Language - Common Patterns

All communication with the server is in JSON (Content-Type: application/json). Our REST API is supposed to follow the "Level 2" maturity level of the Richardson Maturity Model. This means that for any given typeof resource (say a DiaryEntry), we usually have at least the following endpoints:

  • GET /diary: Returns a (paged) list of DiaryEntry.
  • GET /diary/<id>: Returns the unique DiaryEntry with the id <id>. Often the id is simply a date string like 2017-02-23.
  • PUT /diary/<id> with a body containing a complete DiaryEntry: Store the provided entry on the server.
  • DELETE /diary/<id>: Delete the entry with the <id> from the server.

The server uses standard HTTP status codes to signal the result of the operation:

  • 200: Everything is ok (The documents are returned (GET) or the action has been completed successfully (PUT, DELETE)).
  • 401: Access denied (this usually means the auth token has expired or is invalid)
  • 403: Bad request (for PUT, this usually means the request is not valid JSON or some required fields are missing or are in the wrong format (like date strings))
  • 404: Not found - the API endpoint does not exist or the entry has been deleted or does not exist.
  • 5xx (like 500): something went horribly wrong on the server. You might want to try later.

4xx error codes mean that you should not try to send the very same request again without changing, e.g., the login token (in case of 401) or fixing the input (403). 5xx error codes can usually be retried after a while. If the error persists, it's a bug on the server.

Querying Paged Lists

Lists of health records returned by the server are typically paged lists that do not return all results on the server but only a subset. For, the endpoint accepts the following query parameters:

  • count: the number of results to return (page size)
  • offset: the number of the first result to fetch (starting with 0)

For example, to query the 25th-34th (including) diary entries, you may GET the URI /diary?count=10&offset=25.

The server responds with a JSON document that contains the result list and paging information as well as the total number of entries on the server:

{
    "offset": 25,
    "count": 10,
    "totalCount": 27,
    "results": [ { <result one> }, { <result two> } ]
}

Chart

  • GET /chart/csv (authenticated): Returns a CSV file of the health records over time suitable for drawing charts. First line includes the column headers. More columns can be added when needed.

Diary

  • /diary (LIST, GET single, PUT, DELETE as above, authenticated)
export interface DiaryEntry {
    date: string;             // YYYY-MM-DD -- Id of the entry
    pain: number;             // 0-10, integers
    diseaseActivity: number;  // 0-10
    fatigue: number;          // 0-10
    prednisoloneDose: number; // decimal such as 10.0 or 7.5
    additionalDrugs: string;  // text (entered by the user)
    tenderJoints: string;     // text
    comments: string;         // text
}

Drug tolerance

  • /drugtolerance (LIST, GET single, PUT, DELETE as above, authenticated)
export interface DrugToleranceEntry {
    date: string;            // date - id of the entry
    atcCode: string;         // ID of the drug in question (use a placeholder for now)
    tolerance: number;       // 0-10
    comments: string;        // text
}

HAQ

  • GET /haq/sheet: Returns the questionnaire (HAQ). It consists of two pages, having a couple of categories each and in each category there are a couple of questions on "difficulties" (to be scored from 0-3) and on "help" and "tools" needed (to be checked when needed, i.e., 0 or 1). The user has to answer at least one "difficulties" question from six or more categories in total.
export interface HAQSheet {
    pages: HAQPage[];
}

export interface HAQPage {
    categories: HAQCategory[];
}

export interface HAQCategory {
    categoryId: string;
    difficulties: HAQQuestion[];
    help: HAQQuestion[];
    tools: HAQQuestion[];
}

export interface HAQQuestion {
    questionId: string;
}
  • /haq (LIST, GET single, PUT, DELETE as above)
export interface HAQEntry {
    date: string;              // id
    answers: HAQEntryAnswer[]; // the answers given by the user
    score?: number;
}

export interface HAQEntryAnswer {
    questionId: string;
    answer?: number;
}

Laboratory

  • GET /labor/sheet: Returns the blood tests of interest. Blood tests are grouped into categories. Each blood test has a couple of units, because the unit of the actual blood test result varies between different laboratories. The user can enter results for any positive (> 0) number results for blood tests from this list per date.
export interface LaborSheet {
    categories: LaborCategory[];
}
export interface LaborCategory {
    categoryId: string;
    tests: LaborTest[];
}
export interface LaborTest {
    testId: string;
    units: string[];
}
  • /labor/presets: Returns default values for the unit and the reference range for the logged in user.
export interface LaborPreset {
    testId: string;                         // as in LaborTest
    defaultUnit: string;                    // on of the units in LaborTest
    ranges: LaborReferenceRangePreset[];
}
export interface LaborReferenceRange {
    upper: number;                         // decimal number, decimal scale at most 1 (xx.x)
    lower: number;                         // decimal number, decimal scale at most 1
}
export interface LaborReferenceRangePreset extends LaborReferenceRange {
    unit: string;                          // as in LaborTest
}
  • /labor (LIST, GET single, PUT, DELETE as above, authenticated): The actual blood test results.
export interface LaborEntry {
    date: string;                         // id
    results: LaborEntryResult[];
}
export interface LaborEntryResult {
    testId: string;
    unit: string;
    result?: number;
    referenceRange?: LaborReferenceRange;
}

Joint sheet

  • Does not exist yet.
⚠️ **GitHub.com Fallback** ⚠️