Back to top

API Documentation

FORMAT: 1A HOST: http://orange-api.amida-demo.com/api/

Orange API

Orange is a medication adherence app. This is a quasi-REST API for the Orange backend, primarily allowing sharing between patients and caregivers.

All API endpoints must be prefixed with a version number: for example, /v1/auth/token not just /auth/token. Currently v1 is the only API version.

All data should be sent JSON-encoded, and all responses are returned in JSON. Generally speaking, null should be sent to denote an optional field not being present (so, for example, sending null to a PUT update request will remove the field from the instance’s data, but just leaving out that field in the request will leave the field as is in the data).

Throughout this document, we make the distinction between a user and a patient. A user is an email/password pair, used to sign into the app, authenticate with the API, and so on. A patient is someone we hold medication/adherence/etc data for. There is a many-to-many association between users and patients: one user may own many patients (for example, a mother collecting data both for herself and her son), and one patient can be owned by many users (the concept of caregivers: the care of the son – the patient – can be managed by both the mother and the father – the users).

This is a private API, and if you have permission to use it you’ll already have a client secret in the form of a hexstring. This should be sent in the X-Client-Secret header, for example

X-Client-Secret: CLIENT_SECRET

Not sending a client secret, or sending an invalid one, will result in a 401 HTTP error with the body

{
    success: false,
    errors: ['invalid_client_secret']
}

Response Status Codes

Success

All successful requests return responses with the following error codes:

  • GET, PUT and DELETE return 200 on success

  • POST returns 201 on success

Error

Error responses have standard HTTP error codes, along with an array of machine-readable error slugs in the errors key of the JSON response.

For example, when attempting to access user details without authentication

Status: 401 Access denied
{
    success: false,
    errors: ['wrong_email_password']
}

If an unknown error occurs, the response code will be 500 and errors will contain the unknown_error key.

Authentication

Orange API uses access token authentication, like many REST services and similar to (and in fact a semi-compatible subset of) OAuth2. First you use stored user credentials (see POST /auth/token below) to generate an access token, and then pass this access token into the Authorization header of all other requests. All requests apart from user registration and token generation need this authentication.

Precisely, the access token should be sent in the Authorization header in the form

Authorization: Bearer ACCESS_TOKEN

and should be sent in plaintext, not base64 encoded.

Access Tokens

Retrieve an Access Token
POST/auth/token

Use an email/password of an existing user to generate an access token. The access token will expire when the user changes their password, or when it is not in that user’s 5 most recently generated access tokens (whichever happens first).

Example URI

POST /auth/token
URI Parameters
HideShow
email
string (required) 

the email address of the user

password
string (required) 

the corresponding password

Request
HideShow
Body
{
    email: "foo@bar.com",
    password: "foobar"
}
Response  201
HideShow

Errors

  • email_required (400) - no email address specified

  • password_required (400) - no password specified

  • wrong_email_password (401) - wrong email address/password combination

  • login_attempts_exceeded (403) - there have been too many incorrect email

Body
{
    access_token: "abcdefgh123456789",
    success: true
}

Users

User

Register a New User
POST/user

Register a new user, and create a new patient for them as well.

Example URI

POST /user
URI Parameters
HideShow
email
string (required) 

The email address of the new user. Validated to make sure it’s a valid email address.

password
string (required) 

the password of the new user

first_name
string (optional) 

the first name of the new user

last_name
string (optional) 

the last name of the new user

phone
string (optional) 

the phone number of the new user

role
string (required) 

the role of the new user “user” or “clinician”

Request
HideShow
Body
{
    email: "foo@bar.com",
    password: "foobar",
    first_name: "Foo",
    last_name: "Bar",
    phone: "6177140000",
    role: "clinician"
}
Response  201
HideShow

Errors

  • email_required (400) - no email address specified

  • password_required (400) - no password specified

  • invalid_email (400) - the email address specified is not a valid one

  • invalid_role (400) - the role specified is not a valid one

  • user_already_exists (400) - there is already a user with that email address

Body
{
    email: "foo@bar.com",
    first_name: "Foo",
    last_name: "Bar",
    phone: "6177140000",
    role: "clinician",
    success: true
}

View User Info
GET/user

Get basic metadata about the current user.

Example URI

GET /user
Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

Body
{
    email: "foo@bar.com",
    first_name: "Foo",
    last_name: "Bar",
    phone: "6177140000",
    role: "clinician",
    npi: "1245319599",
    success: true
}

Change User Info
PUT/user

Change basic metadata about the current user, including their password.

Example URI

PUT /user
URI Parameters
HideShow
first_name
string (optional) 

new first name

last_name
string (optional) 

new last name

phone
string (optional) 

new phone number

npi
string (optional) 

new npi (only will work if the user’s role is “clinician”)

password
string (optional) 

New password. Note that if the password is changed, all access tokens are revoked.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    first_name: "Foo",
    last_name: "Baz",
    phone: "6177140001",
    npi: "1245319599",
    password: "foobaz"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_npi (400) - the npi specified is not a valid one

Body
{
    email: "foo@bar.com",
    first_name: "Foo",
    last_name: "Baz",
    phone: "6177140001",
    role: "clinician",
    npi: "1245319599",
    success: true
}

Delete User
DELETE/user

Permanently remove the user, including all metadata stored on them (e.g., their password). Patients accessible only to this user will be deleted, but patients viewable by other users will not be deleted.

Example URI

DELETE /user
Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

Body
{
    email: "foo@bar.com",
    first_name: "Foo",
    last_name: "Bar",
    phone: "6177140000",
    role: "clinician",
    npi: "1245319599",
    success: true
}

Reset Password

Reset a User's Password
POST/user/reset_password

Reset password for a specific user. Takes the email address of a user, generates a new temporary password for them, emails them the new password, and revokes all existing access tokens.

Example URI

POST /user/reset_password
URI Parameters
HideShow
email
string (required) 

The email address of the user whose password should be reset. Must correspond to an existing user account.

Request
HideShow
Body
{
    email: "foo@bar.com"
}
Response  201
HideShow

Errors

  • email_required (400) - no email address specified

  • user_not_found (400) - an existing user with that email address was not found

Body
{
    email: "foo@bar.com",
    success: true
}

Requests

Each user can request access to another user’s patients. This is done by making a POST request to /requested, after which the request can be viewed at GET /requested and cancelled at DELETE /requested/:id if needed.

The user to which the request was made can then view the request at /requests and close it by making a DELETE request to /requests/:id. As discussed in greater detail below, this DELETE request should contain a JSON body with either status: accepted or status: rejected depending on the outcome. Note that DELETEing the request does not actually share any patients: that must be done seperately using the POST /patients/:patientid/shares endpoint. This way the user can choose to selectively share just some of their patients.

Deleted requests are still shown, so the status field should be used to determine between requests. Possible values are pending, cancelled, accepted and rejected.

Note that if user A requests access from user B, the request ID for user A (at /requested) is not necessarily the same as the request ID for user B (at /requests).

Requests From User

Create new Request
POST/requested

Request access to another user’s patients from the current user.

Example URI

POST /requested
URI Parameters
HideShow
email
string (required) 

email address of the user to request access from

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    email: "another@user.com"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • email_required (400) - an email address must be specified

  • invalid_email (400) - the email address specified does not correspond to an existing user

  • already_requested (400) - a request has already been made to that user from this user

  • cant_request_yourself (400) - a request can’t be made to request sharing with yourself

Body
{
    id: 1,
    email: "another@user.com",
    status: "pending",
    success: true
}

List Requests
GET/requested

View a list of all requests the current user has made.

Example URI

GET /requested
URI Parameters
HideShow
limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or email and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

email
string (optional) 

Filter results by email address of the user the request was made to. Matches any email addresses that contain the specified email as a substring.

status
string (optional) 

Filter results by request status (matches exactly).

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_status (400) - the specified status to filter by is not pending, cancelled, accepted or rejected

Body
{
    requests: [
        {
            id: 1,
            email: "another@user.com"
            status: "pending",
        },
        ...
    ],
    count: 2,
    success: true
}

Request From User

Cancel Request
DELETE/requested/{requestid}

Cancel an existing request to access another user’s patient data.

Example URI

DELETE /requested/requestid
URI Parameters
HideShow
requestid
integer (required) 

unique ID of the request (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_request_id (404)

    a request made with the specified ID by the current user was not found, or it was already cancelled or closed

Body
{
    id: 1,
    email: "another@user.com",
    status: "cancelled",
    success: true
}

Requests to User

List Requests
GET/requests

View a list of all requests made to the current user by other users requesting the current user to share their patient data.

Example URI

GET /requests
URI Parameters
HideShow
limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or email and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

email
string (optional) 

Filter results by email address of the user the request was made from. Matches any email addresses that contain the specified email as a substring.

status
string (optional) 

Filter results by request status (matches exactly).

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_status (400) - the specified status to filter by is not pending, cancelled, accepted or rejected

Body
{
    requests: [
        {
            id: 1,
            email: "original@user.com",
            status: "pending"
        },
        ...
    ],
    count: 2,
    success: true
}

Request To User

Close Request
DELETE/requests/{requestid}

Close a request another user has made to access the current user’s data. A status key should be sent with this request with a value of either accepted or rejected indicating the outcome of the request. Note that status is used purely to notify the user, and status=accepted does not actually share any data with the requesting user. Instead, that must be done by making requests to the POST /patients/:patientid/shares endpoint. This way the user can selectively choose to share just some of thier patients.

Example URI

DELETE /requests/requestid
URI Parameters
HideShow
requestid
integer (required) 

unique ID of the request (url)

status
string (required) 

Outcome of the request. Must be either accepted or rejected.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    status: "accepted"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_request_id (404)

    a request made with the specified ID by the current user was not found, or it was already cancelled or closed

  • invalid_status (400) - the status body key must be either accepted or rejected

Body
{
    id: 1,
    email: "another@user.com",
    status: "accepted",
    success: true
}

Patients

Remember, patients are the resources for which we actually store medication/etc data, rather than users (and we have a many to many association between patients and users).

When a user is created, a corresponding patient for them is also created. The user can then optionally create more patients for e.g., children dependents.

Patients can then be shared with other users. There are three levels of sharing: family prime (prime), family (family) and anyone (anyone). Family prime is intended to represent family extremely close to the patient (e.g., parents) who should have access to almost everything, family is intended for wider family of the patient, and anyone is intended for everyone else (e.g., doctors).

At the patient level, a user’s access to data is determined by which one of the above three groups they’re a member of. API requests can be made to set global read (read) or read-write (write) permissions for each of the three share groups for each patient, as well as an overriding read/write permission for each user the patient is shared with (so each share has either read, write or default permissions, where default means to just use the patient-wide permissions for the relevant share group). However, note that these permissions are all set to sensible defaults: specifically all three share groups have write access by default, and all users created have default share permissions. Note that this does not grant every user a patient is shared with full read-write access to their data, because medications have a slightly more complex permissions structure (described below).

In a patient response object, access_anyone, access_family and access_prime represent the permissions of the anyone/family/family prime share user groups respectively. The access field denotes the current user’s access to the patient, and will always be either read or write (if it is set to default, it will be changed to the relevant value; this is not true of the /patients/:id/share/ endpoints).

These generic permissions control access to most of a patient’s resources, but medications, journal entries, doses and schedules are slightly more complicated. As described in the medications section, each medication has its own additional set of access controls. For each of their medications, the patient can explicitly set the access level of family prime, family and anyone. This then controls access to that medication, any journal entries tagged with that medication, any schedule events for that medication, and any dose events for that medication.

There are four access levels that can be set for each group on this per-medication basis: read, write, none and default. read and write behave as they do in a patient-wide context, and none means that that user group has no access at all to the medication or it’s resources. default is slightly more complicated: rather than just delegating straight to the patient-level permissions, it has a slightly different meaning depending on the share group and medication details:

  • For an anyone share, default gives the user read-only access

  • For a family share on an as-needed medication (including medications that are both regular and as-needed), default gives the user write access.

  • For a family share on a medication that is not as-needed (so is regular-only), default gives the user read-only access.

  • For a prime share, default delegates to the patient-level permissions: it first looks at any explicit permissions specified in the share itself, and if that’s set to default then it looks as access_prime in the patient data.

There is one exception to this rule. The user who creates a medication is recorded as the creator of that medication, and they always have write access to that medication (even if, for example, the patient is shared with the user through the anyone group and the medication has access_anyone="default" (which would usually give them read-only access), that user will still have write access).

Each patient returned by the API has an avatar field containing the path of that patient’s avatar (image) endpoint. As documented below, GETting this path returns the user’s avatar (initially a default image) and POSTing to this path with raw image data sets the avatar to the POSTed data.

Each patient returned also has a creator field (which cannot be modified) containing the email address of the user who created the patient, and a me boolean field representing whether the patient corresponds to that user’s “own log”. me is true for the patient automatically created when a user registers, and false otherwise.

User's Patients

Create new Patient
POST/patients

Create a new patient, initially shared with the current user with write permissions, and no-one else. For example, this should be called upon initial setup of the app to create a patient for the end user, and can later be called to create a new patient representing the child of the patient.

Example URI

POST /patients
URI Parameters
HideShow
first_name
string (required) 

the first name of the patient

last_name
string (optional) 

the last name of the patient

birthdate
string (optional) 

Optional date of birth of the patient, formatted as an ISO 8601 YYYY-MM-DD

sex
string (optional) 

String representing sex of the user. Must be “male”, “female”, “other” or “unspecified”.

phone
string (optional) 

Optional phone number of the patient, formatted as a string

access_anyone
string (required) 

The default access permissions that users this patient is shared with under the anyone group should have. Must be either read or write. Defaults to write.

access_family
string (required) 

The default access permissions that users this patient is shared with under the family group should have. Must be either read or write. Defaults to write.

access_prime
string (required) 

The default access permissions that users this patient is shared with under the prime group should have. Must be either read or write. Defaults to write.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    first_name: "Dependent",
    last_name: "Patient",
    birthdate: "1990-01-01",
    sex: "male",
    phone: "6177140000",
    access_anyone: "read",
    access_family: "read",
    access_prime: "write"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • first_name_required (400) - no first name specified

  • invalid_sex (400)

    the sex field, if passed, must be either male, female, other or unspecified

  • invalid_birthdate (400) - the birthdate field, if passed, must be a valid YYYY-MM-DD date

  • invalid_access_anyone (400) - the access_anyone field, if passed, must be either read or write

  • invalid_access_family (400) - the access_family field, if passed, must be either read or write

  • invalid_access_prime (400) - the access_prime field, if passed, must be either read or write

Body
{
    id: 1,
    first_name: "Dependent",
    last_name: "Patient",
    birthdate: "1990-01-01",
    sex: "male",
    phone: "6177140000",
    avatar: "/v1/patients/1/avatar.jpg",
    creator: "foo@bar.com",
    me: true,
    access_anyone: "read",
    access_family: "read",
    access_prime: "write",
    access: "write",
    group: "owner",
    success: true
}

List Patients
GET/patients

View a list of all patients the current user has access to (either read or write).

Example URI

GET /patients
URI Parameters
HideShow
limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id, first_name or last_name, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

first_name
string (optional) 

Filter results by first name of patient. Performs fuzzy matching.

last_name
string (optional) 

Filter results by last name of patient. Performs fuzzy matching.

group
string (optional) 

Filter results by group of patient. Matches exactly.

creator
string (optional) 

Filter results by email address of creator. Matches any email addresses that contain the specified email as a substring.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_group (400)

    the specified group to filter by is invalid (must be owner, anyone, family or prime)

Body
{
    patients: [
        {
            id: 1,
            first_name: "Dependent",
            last_name: "Patient",
            birthdate: "1990-01-01",
            sex: "male",
            phone: "6177140000",
            avatar: "/v1/patients/1/avatar.jpg",
            creator: "foo@bar.com",
            me: true,
            access_anyone: "read",
            access_family: "read",
            access_prime: "write",
            access: "write",
            group: "owner"
        },
        ...
    ],
    count: 2,
    success: true
}

Patient

View Patient Info
GET/patients/{patientid}

View the name of a specific patient as well as the current user’s access (read or write) to them, and the group the patient is shared with them through (either owner, prime, family or anyone). To view and modify other user’s access to this patient, see the /patients/{id}/shares endpoint.

Example URI

GET /patients/patientid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

Body
{
    id: 1,
    first_name: "Dependent",
    last_name: "Patient",
    birthdate: "1990-01-01",
    sex: "male",
    phone: "6177140000",
    avatar: "/v1/patients/1/avatar.jpg",
    creator: "foo@bar.com",
    me: true,
    access_anyone: "read",
    access_family: "read",
    access_prime: "write",
    access: "write",
    group: "prime",
    success: true
}

Update Patient Info
PUT/patients/{patientid}

Update a patients’ details. This requires the user to have write access to the patient. Name, group and access level can be modified here. The access level can be modified in two ways: setting access (to read, write, none or default) will set the access level the current user has to the patient, and setting access_prime, access_family or access_anyone (to read or write) will set the group-wide access levels for the patient.

The owner of a patient cannot change their access level from write or their group from owner.

Setting access to none will stop sharing the patient with the current user.

Example URI

PUT /patients/patientid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

first_name
string (optional) 

new first name of the patient

last_name
string (optional) 

new last name of the patient

birthdate
string (optional) 

Optional date of birth of the patient, formatted as an ISO 8601 YYYY-MM-DD

sex
string (optional) 

String representing sex of the patient. Must be “male”, “female”, “other” or “unspecified”.

phone
string (optional) 

New phone number of the patient

access
string (optional) 

Explicitly set the patient’s access level to read, write, default or none. none stops sharing the patient with the user. This is permanent and potentially irreversible, and hence should be used with caution.

group
string (optional) 

Change the group of the current user. If the user is the owner, their group cannot be changed. Otherwise, the group can be changed between prime, family and anyone.

access_anyone
string (optional) 

Change the access level of the anyone user share group. Must be either read or write.

access_family
string (optional) 

Change the access level of the family user share group. Must be either read or write.

access_prime
string (optional) 

Change the access level of the prime user share group. Must be either read or write.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    first_name: "Gin",
    last_name: "Smith",
    birthdate: "1991-01-01",
    sex: "female",
    phone: "6177140001",
    access: "write",
    group: "family",
    access_anyone: "read",
    access_family: "read",
    access_prime: "read"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_sex (400)

    the sex field, if passed, must be either male, female, other or unspecified

  • invalid_birthdate (400) - the birthdate field, if passed, must be a valid YYYY-MM-DD date

  • invalid_access (400) - the access field, if passed, must be either read, write, default or none

  • invalid_group (400) - the group field, if passed, must be either prime, family or anyone

  • is_owner (400) - the share belongs to the user owning the patient so cannot be changed

  • invalid_access_anyone (400) - the access_anyone field, if passed, must be either read or write

  • invalid_access_family (400) - the access_family field, if passed, must be either read or write

  • invalid_access_prime (400) - the access_prime field, if passed, must be either read or write

Body
{
    id: 1,
    first_name: "Gin",
    last_name: "Smith",
    birthdate: "1991-01-01",
    sex: "female",
    phone: "6177140001",
    avatar: "/v1/patients/1/avatar.jpg",
    creator: "foo@bar.com",
    me: true,
    access_anyone: "read",
    access_family: "read",
    access_prime: "read",
    access: "write",
    group: "family",
    success: true
}

Delete Patient
DELETE/patients/{patientid}

Remove a patient for whom the user is the owner. This permanently removes the patient, all of their associated habits, doctors, pharmacies, medications and dose events for all users the patient is shared with and as such should be used with extreme caution.

To completely remove a patient from the user’s sphere of influence, note that PUT should be called with access="none" rather than this method.

Example URI

DELETE /patients/patientid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

Body
{
    id: 1,
    first_name: "Gin",
    last_name: "Smith",
    birthdate: "1991-01-01",
    sex: "female",
    phone: "6177140001",
    avatar: "/v1/patients/1/avatar.jpg",
    creator: "foo@bar.com",
    me: true,
    access_anyone: "read",
    access_family: "read",
    access_prime: "write",
    access: "write",
    group: "owner",
    success: true
}

Patient Report

Generate Report
GET/patients/{patientid}.pdf

View a PDF report of the patient’s medications and dosage logs. Only those journal entries, medications and dose events that the user has read access to (remember medications can override patient-wide access permissions) are shown.

Report is returned as a PDF file with Content-Type: "application/pdf".

Example URI

GET /patients/patientid.pdf
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific)

start_date
string (optional) 

YYYY-MM-DD (in patient’s local timezone) of the date to start the report from. Defaults to the start of the current month, or the start of the month end_date is in if end_date is specified.

end_date
string (optional) 

YYYY-MM-DD (in patient’s local timezone) of the date to start the report from. Defaults to the end of the current month, or the end of the month start_date is in if start_date is specified.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_start (400) - invalid YYYY-MM-DD value for start_date

  • invalid_end (400) - invalid YYYY-MM-DD value for end_date

Body
raw PDF data

Patient Data Dump

View JSON Data Dump
GET/patients/{patientid}.json

View a data dump of all data associated with a patient (specifically the patient metadata, habits, journal entries, doctors, pharmacies, medications and dose events). Only those journal entries, medications and dose events that the user has read access to (remember medications can override patient-wide access permissions) are shown.

Example URI

GET /patients/patientid.json
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific)

start_date
string (optional) 

YYYY-MM-DD (in patient’s local timezone) of the date to start the dump from. Defaults to the start of the current month, or the start of the month end_date is in if end_date is specified.

end_date
string (optional) 

YYYY-MM-DD (in patient’s local timezone) of the date to start the dump from. Defaults to the end of the current month, or the end of the month start_date is in if start_date is specified.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_start (400) - invalid YYYY-MM-DD value for start_date

  • invalid_end (400) - invalid YYYY-MM-DD value for end_date

Body
{
    id: 34,
    first_name: "Patient 11",
    last_name: "number 11",
    birthdate: "1990-01-01",
    sex: "male",
    phone: "6177140000",
    avatar: "/v1/patients/34/avatar.png",
    creator: "foo@bar.com",
    me: true,
    access_anyone: "read",
    access_family: "read",
    access_prime: "write",
    group: "anyone",
    access: "read",
    habits: {
        wake: null,
        sleep: null,
        breakfast: null,
        lunch: null,
        dinner: null,
        tz: "Etc/UTC"
    },
    entries: [
        {
            date: "2015-07-15T13:18:21.000-04:00",
            text: "example journal entry",
            medication_ids: [
                1
            ],
            mood: "",
            id: 1
        }
    ],
    doctors: [
        {
            name: "test doctor",
            phone: "",
            address: "",
            notes: "",
            id: 1
        }
    ],
    pharmacies: [
        {
            name: "test pharmacy",
            phone: "",
            address: "",
            hours: {
                monday: {},
                tuesday: {},
                wednesday: {},
                thursday: {},
                friday: {},
                saturday: {},
                sunday: {}
            },
            notes: "",
            id: 1
        }
    ],
    medications: [
        {
            name: "test medication",
            rx_norm: "",
            rx_number: "",
            ndc: "",
            dose: {
                quantity: 1,
                unit: "dose"
            },
            route: "",
            form: "",
            quantity: 1,
            type: "",
            fill_date: null,
            doctor_id: null,
            pharmacy_id: null,
            access_anyone: "default",
            access_family: "default",
            access_prime: "default",
            number_left: null,
            schedule: {
                as_needed: true,
                regularly: false
            },
            id: 1
        }
    ],
    doses: [
        {
            medication_id: 1,
            date: "2015-07-15T13:18:21.000-04:00",
            notes: "",
            id: 1
        }
    ],
    shares: [
        {
            is_user: true,
            access: "write",
            group: "owner",
            email: "foo26@bar.com",
            id: 42
        },
        {
            is_user: true,
            access: "default",
            group: "anyone",
            email: "foo25@bar.com",
            id: 43
        }
    ],
    success: true
}

Patient's Avatar

View Patient Avatar
GET/patients/{patientid}/avatar(.ext)

View the image avatar of a specific patient. File extensions can be added to the URL (for example, /patients/1/avatar.jpg, /patients/1/avatar.gif) but the image will not be converted to the format associated with the extension, but instead just returned in whatever format it was stored in. The URL in the avatar field in a patient’s details will automatically include the correct extension for the image.

The user needs read access to the patient.

The Content-Type header will be populated with the correct MIME type.

Example URI

GET /patients/patientid/avatar(.ext)
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

Body
raw image data

Upload Patient Avatar
POST/patients/{patientid}/avatar(.ext)

Upload the image avatar of a specific patient. Again, file extensions can be added to the URL but are ignored and will not be used to convert the image format. Note that for this endpoint, raw binary data should be POSTed rather than application/json-encoded data.

The user needs write access to the patient.

Also note that this endpoint uses POST not PUT contrary to REST resource routing conventions.

Example URI

POST /patients/patientid/avatar(.ext)
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
raw image data
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_image (400) - the POSTed data is an invalid image

Body
{
    success: true,
    avatar: "/v1/patients/1/avatar.gif"
}

Patient's Shared Users

This endpoint represents all of the users a specific patient is shared with: including both read and write access. The IDs in this section represent patient-user relationships, not users themselves, so if patient 1 is shared with user 7 then the shared ID may be 16, rather than 7.

Share with a User
POST/patients/{patientid}/shares

Share a patient’s data (a patient for whom the user has write access) with a new user specified by email address. This user can be an existing app user, but is not required to be: if they are then they’re automatically granted access to the patient’s data, and if they’re not they’re sent an email invitation to install the app, and once they do they’ll receive automatic access to the patient’s data. The is_user field in the response distinguishes between the two cases: it’s true in the case of an existing user, and false in the case of a new user who’s been invited.

An example use case here would be a mother (the user) wanting to share her child’s (the patient’s) data with the father (another user).

Example URI

POST /patients/patientid/shares
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

email
string (required) 

the email address of the user to share data with

access
string (required) 

read, write or default to signify the level of access the user should have to the patient (default means the user has whatever access to the patient the patient-wide permissions give them, whereas read and write explicitly override those patient-wide permissions)

group
string (required) 

The share group to add the user to. Must be either prime, family or anyone.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    email: "care@giver.com",
    access: "read",
    group: "family"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • unauthorized (403) - the current user does not have write access to this patient

  • email_required (400) - an email address to share with must be specified

  • invalid_email (400) - the email address specified is not a valid one

  • access_required (400) - the desired access level must be specified

  • invalid_access (400) - the access string specified is not a valid one (must be either read, write or default)

  • group_required (400) - the share group the user should be added to must be specified

  • invalid_group (400) - the share group the user is not a valid one (must be either prime, family or anyone)

Note that this id is for the user-patient association, not the user ID.

is_user (boolean) signifies whether the user is already an existing user of the app, or whether they’ve been sent an email inviting them to sign up.

Body
{
    id: 1,
    email: "care@giver.com",
    access: "read",
    group: "family",
    is_user: true,
    success: true
}

List all Shared Users
GET/patients/{patientid}/shares

For a patient whom the user has read access, get a list of all users (including the current one) who have (either read or write) access to the patient.

Example URI

GET /patients/patientid/shares
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or email, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

email
string (optional) 

Filter results by email address of user. Matches any email addresses that contain the specified email as a substring.

is_user
boolean (optional) 

filter results by selecting only user that are existing users (as opposed to those who’ve been invited but still haven’t signed up)

access
string (optional) 

filter results by selecting only users with the specified level of access (either read or write)

group
string (optional) 

filter results by selecting only users who are part of the specified share group (either owner, prime, family or anyone)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_is_user (400) - the specified is_user value to filter by is invalid

  • invalid_access (400) - the specified access value to filter by is invalid

  • invalid_group (400) - the specified group value to filter by is invalid

Body
{
    shares: [
        {
            id: 1,
            email: "care@giver.com",
            access: "write",
            group: "family",
            is_user: true
        },
        ...
    ],
    count: 2,
    success: true
}

Shared User

Update Access Level
PUT/patients/{patientid}/shares/{shareid}

Update the access another user has to a patient (the current user of course is required to have write access to this patient). To modify the current user’s access, see the convenience method PUT /patients/:patientid.

Neither access nor group can be modified for the share for a user who owns a patient.

Example URI

PUT /patients/patientid/shares/shareid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

shareid
integer (required) 

unique ID of the patient-user association (not the user ID) (url)

access
string (required) 

read, write or default to signify the new level of access the specified user should have to the patient

group
string (required) 

anyone, family or prime to signify the new sharing group the specified user should be a member of

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    access: "write",
    group: "family"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_share_id (404)

    A patient-user sharing relationship with the specified ID was not found (remember, this is not the same as the user ID)

  • invalid_access (400) - the specified access value to change to is invalid

  • invalid_group (400) - the specified group value to change to is invalid

  • is_owner (400) - the share belongs to the user owning the patient so cannot be modified

Body
{
    id: 1,
    email: "care@giver.com",
    access: "write",
    group: "family",
    is_user: true,
    success: true
}

Stop Sharing with User
DELETE/patients/{patientid}/shares/{shareid}

Stop sharing the specified patient’s data with a specified user. The current user will of course need write access to the patient. To stop sharing a patient with the current user, see the convenience method PUT /patients/:patientid.

The owner’s share cannot be deleted.

Example URI

DELETE /patients/patientid/shares/shareid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (not user-specific) (url)

shareid
integer (required) 

unique ID of the patient-user association (not the user ID) (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_share_id (404)

    A patient-user sharing relationship with the specified ID was not found (remember, this is not the same as the user ID)

  • is_owner (400) - the share belongs to the user owning the patient so cannot be removed

Body
{
    id: 1,
    email: "care@giver.com",
    access: "write",
    group: "family",
    is_user: true,
    success: true
}

Habits

Patient Habits

Habits are real-life preferences of the patient: what time they usually wake up in the morning, what time they usually eat lunch, and so on. Exactly one set of preferences is stored for each patient. The current user will need read access to the patient to view the habits, and write access to set them.

Habits must be in the specific HH:MM a format; for example, 03:59 am and 11:20 pm. These times are in the local timezone of the patient, and will not change if the timezone is updated (for example, if breakfast is set to 10:00 am while the timezone is London/Europe, breakfast will remain as 10:00 am if the timezone is updated to America/New_York. This signifies that if medication is to be taken with food at breakfast every morning, the patient should continue doing that even if the timezone shifts).

Habits (all may be blank, and initially are after registration):

  • wake (time) - what time the patient normally wakes up in the morning. Defaults to 07:00 am.

  • sleep (time) - what time the patient normally goes to sleep at night. Defaults to 08:00 am.

  • breakfast (time) - what time the patient normally eats breakfast. Defaults to 12:00 pm.

  • lunch (time) - what time the patient normally eats lunch. Defaults to 07:00 pm.

  • dinner (time) - what time the patient normally eats dinner. Defaults to 11:00 pm.

  • tz (timezone) - the current timezone of the patient (retrieved automatically from the mobile OS without any user participation required). Should be a valid TZ database timezone (e.g., /London/Europe). Defaults to Etc/UTC (UTC time).

Get Patient Habits
GET/patients/{patientid}/habits

View the patient’s current habits.

Example URI

GET /patients/patientid/habits
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

Body
{
    wake: "07:00 am",
    sleep: "11:00 pm",
    breakfast: "08:00 am",
    lunch: "12:00 pm",
    dinner: "07:00 pm",
    tz: "Etc/UTC",
    success: true
}

Set Patient Habits
PUT/patients/{patientid}/habits

Set the patient’s habits. The current user will need write access to the patient.

Example URI

PUT /patients/patientid/habits
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

wake
time (optional) 

what time the patient normally wakes up in the morning

sleep
time (optional) 

what time the patient normally goes to sleep at night

breakfast
time (optional) 

what time the patient normally eats breakfast

lunch
time (optional) 

what time the patient normally eats lunch

dinner
time (optional) 

what time the patient normally eats dinner

tz
timezone (optional) 

the current user timezone

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    wake: "06:00 am",
    sleep: "10:00 pm",
    breakfast: "07:00 am",
    lunch: "11:00 am",
    tz: "London/Europe",
    dinner: "06:00 pm"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_wake (400) - the wake time passed is not formatted as HH:MM

  • invalid_sleep (400) - the wake time passed is not formatted as HH:MM

  • invalid_breakfast (400) - the wake time passed is not formatted as HH:MM

  • invalid_lunch (400) - the wake time passed is not formatted as HH:MM

  • invalid_dinner (400) - the wake time passed is not formatted as HH:MM

  • invalid_tz (400) - the timezone passed is not a valid TZ database timezone

Body
{
    wake: "06:00 am",
    sleep: "10:00 pm",
    breakfast: "07:00 am",
    lunch: "11:00 am",
    dinner: "06:00 pm",
    tz: "London/Europe",
    success: true
}

Journal Entries

Basic free-text journal for the patient to enter notes about their day and such in. While medications can be tagged in journal entries, entries that correspond exactly to dose events should probably just be stored in the notes field of a dose event.

Hashtags are parsed from each journal entry and returned in a hashtags array of strings.

Journal Entries

Create an Entry
POST/patients/{patientid}/journal

Store details of a new journal entry (the current user will need write access to both the patient and every medication in medication_ids).

Example URI

POST /patients/patientid/journal
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

date
string (required) Example: 2015-05-31T19:27:09+00:00

ISO 8601 combined date-time in UTC representing the date and time to be associated with the journal entry. Should probably allow user entry of this, but default to the time the user wrote the entry.

text
string (required) 

free-form text field.

medication_ids
integers (optional) 

optional list of medication IDs to ‘tag’ the journal entry with

mood
string (optional) 

mood of the patient as they wrote the journal entry

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an amazing day today, perhaps thanks in part to taking one more #Adderall than I was meant to this morning!! I #love you #Orange guys soooo much it's insane, but I should probably #go now to avoid #typing #too #much #hashtags #omgilovehashtags #Adderall",
    medication_ids: [1,4],
    mood: "Happy",
    hashtags: ["Adderall", "love", "Orange", "go", "typing", "too", "much", "hashtags", "omgilovehashtags"],
    success: true
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • text_required (400) - text for the journal entry must be provided

  • date_required (400) - a datetime for the entry must be provided

  • invalid_date (400) - the date given is not in valid ISO 8601 format

  • invalid_medication_id (400) - the medications list contains an invalid entry for which a corresponding medication cannot be found

Body
{
    id: 1,
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an amazing day today, perhaps thanks in part to taking one more #Adderall than I was meant to this morning!! I #love you #Orange guys soooo much it's insane, but I should probably #go now to avoid #typing #too #much #hashtags #omgilovehashtags #Adderall",
    medication_ids: [1,4],
    mood: "Happy",
    hashtags: ["Adderall", "love", "Orange", "go", "typing", "too", "much", "hashtags", "omgilovehashtags"],
    success: true
}

Retrieve all Entries
GET/patients/{patientid}/journal

Get a list of all journal events for the patient. Includes full information on each, but each medication ID in medication_ids is not expanded out into a full medication object. To call this endpoint successfully, the user will need read access to the patient. Further, each journal entry will only be shown if the user has read access to all medications tagged in that journal entry.

Example URI

GET /patients/patientid/journal
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or date, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

start_date
string (optional) 

Restrict results to entries that took place after this date. Must be a valid ISO 8601 datetime. Defaults to 0.

end_date
string (optional) 

Restrict results to entries that took place before this date. Must be a valid ISO 8601 datetime. Defaults to infinity.

medication_ids
array of integers (optional) 

Restrict results to journal entries that include (at least all of) these medications.

text
string (optional) 

Restrict results to journal entries containing this text (fuzzy-matching)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_start (400) - the specified start date is an invalid ISO 8601 datetime

  • invalid_end (400) - the specified end date is an invalid ISO 8601 datetime

  • invalid_medication_id (400) - the medications list contains an invalid entry for which a corresponding medication cannot be found

Body
{
    entries: [
        {
            id: 1,
            date: "2015-05-31T19:27:09+00:00",
            text: "Had an amazing day today, perhaps thanks in part to taking one more Adderall than I was meant to this morning!! I #love you #Orange guys soooo much it's insane, but I should probably #go now to avoid #typing #too #much #hashtags #omgilovehashtags #Adderall",
            mood: "Happy",
            hashtags: ["Adderall", "love", "Orange", "go", "typing", "too", "much", "hashtags", "omgilovehashtags"],
            medication_ids: [1,4]
        },
        ...
    ],
    count: 46,
    success: true
}

Journal Entry

Retrieve One Entry
GET/patients/{patientid}/journal/{journalid}

View information on an individual journal entry. medication_ids is helpfully expanded out into medications. The current user will need read access to both the patient’s data and all medications tagged in medication_ids.

Example URI

GET /patients/patientid/journal/journalid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

journalid
integer (required) 

unique ID of the journal entry

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_journal_id (404) - an entry with that ID was not found

Body
{
    id: 1,
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an amazing day today, perhaps thanks in part to taking one more Adderall than I was meant to this morning!! I #love you #Orange guys soooo much it's insane, but I should probably #go now to avoid #typing #too #much #hashtags #omgilovehashtags #Adderall",
    mood: "Happy",
    hashtags: ["Adderall", "love", "Orange", "go", "typing", "too", "much", "hashtags", "omgilovehashtags"],
    medications: [
        {
            id: 1,
            name: "Loratadine",
            rx_norm: "324026",
            pharmacy_id: 1
        },
        {
            id: 4,
            name: "Adderall",
            rx_norm: "123456789",
            pharmacy_id: 7
        }
    ],
    success: true
}

Change an Entry
PUT/patients/{patientid}/journal/{journalid}

Change information (medications, date and/or text) of a single journal entry. The current user will need write access to the patient, write access to every medication tagged in the old medication_ids and write access to every medication tagged in the newly-updated medication_ids.

Example URI

PUT /patients/patientid/journal/journalid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

journalid
integer (required) 

unique ID of the entry (url)

date
string (optional) 

new ISO 8601 datetime to change the entry date to

medication_ids
array of integers (optional) 

Array of medication IDs. This will overwrite the previous list, so make sure to list all medication IDs for the entry, not just new ones.

text
string (optional) 

String to change the actual text of the entry to. Cannot be blank if present.

mood
string (optional) 

mood of the patient as they wrote the journal entry

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an absolute amazeballs day today, omg I love Adderall so much it's the greatest thing ever.",
    mood: "amazeballs",
    medication_ids: [2,3,8,9,10]
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_journal_id (404) - a journal entry with that ID was not found

  • invalid_date (400) - the date field specified is not in valid ISO 8601 format

  • text_required (400) - if the text field is present, it cannot be blank

  • invalid_medication_id (400) - the medications list contains an invalid entry for which a corresponding medication cannot be found

Body
{
    id: 1,
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an absolute amazeballs day today, omg I love Adderall so much it's the greatest thing ever.",
    mood: "amazeballs",
    hashtags: [],
    medication_ids: [2,3,8,9,10]
    success: true
}

Delete an Entry
DELETE/patients/{patientid}/journal/{journalid}

Remove a single journal entry. The current user will need write access to both the patient and all medications tagged in medication_ids.

Example URI

DELETE /patients/patientid/journal/journalid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

journalid
integer (required) 

unique ID of the journal entry (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_journal_id (404) - a journal entry with that ID was not found

Body
{
    id: 1,
    date: "2015-05-31T19:27:09+00:00",
    text: "Had an absolute amazeballs day today, omg I love Adderall so much it's the greatest thing ever.",
    mood: "amazeballs",
    hashtags: [],
    medication_ids: [2,3,8,9,10]
    success: true
}

Doctors

Basic contact details for all of the doctors who’ve prescribed medication to a specified patient.

Doctors Collection

Create a Doctor
POST/patients/{patientid}/doctors

Store details of a new doctor for the specified patient (the current user will need write access to the patient).

Example URI

POST /patients/patientid/doctors
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

name
string (required) 

full name of the doctor

phone
string (optional) 

contact phone number for the doctor

address
string (optional) 

Postal address of the doctor. Newlines can optionally be used to split lines.

notes
string (optional) 

freeform text notes about the doctor by the patient

title
string (optional) 

position of doctor

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Dr. X",
    phone: "(617) 617-6177",
    address: "Doctor Street, DC, 20052",
    notes: "Love this doc!",
    title: "Primary Care Physician"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • name_required (400) - a name must be provided

Body
{
    id: 1,
    name: "Dr. X",
    phone: "(617) 617-6177",
    address: "Doctor Street, DC, 20052"
    notes: "Love this doc!",
    title: "Primary Care Physician"
    success: true
}

Retrieve all Doctors
GET/patients/{patientid}/doctors

Get a list of all the patient’s doctors. Includes full information on each. The current user will need read access to the patient.

Example URI

GET /patients/patientid/doctors
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or name, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

name
string (optional) 

Filter results by name of doctor. Performs fuzzy matching.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

Body
{
    doctors: [
        {
            id: 1,
            name: "Dr. X",
            phone: "(617) 617-6177",
            address: "Doctor Street, DC, 20052",
            title: "Primary Care Physician",
            notes: "Love this doc!"
        },
        ...
    ],
    count: 3,
    success: true
}

Doctor

Retrieve a Doctor
GET/patients/{patientid}/doctors/{doctorid}

View information on an individual doctor. The current user will need read access to the patient.

Example URI

GET /patients/patientid/doctors/doctorid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

doctorid
integer (required) 

unique ID of the doctor

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_doctor_id (404) - a doctor with that ID was not found

Body
{
    id: 1,
    name: "Dr. X",
    phone: "(617) 617-6177",
    address: "Doctor Street, DC, 20052",
    notes: "Love this doc!",
    title: "Primary Care Physician",
    success: true
}

Change a Doctor's Info
PUT/patients/{patientid}/doctors/{doctorid}

Change information (name, phone and/or address) of an individual doctor. The current user will need write access to the patient data.

Example URI

PUT /patients/patientid/doctors/doctorid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

doctorid
integer (required) 

unique ID of the doctor (url)

name
string (optional) 

Full name of the doctor. Must not be blank.

phone
string (optional) 

contact phone number for the doctor

address
string (optional) 

postal address, in the format specified above in POST

notes
string (optional) 

freeform text notes about the doctor by the patient

title
string (optional) 

position of doctor

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Dr. Y",
    phone: "(716) 716-7166",
    address: "Doctor Street, DC, 20052",
    title: "Primary Care Physician",
    notes: "Love this doc the most!"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • name_required (400) - a name must be provided

  • invalid_doctor_id (404) - a doctor with that ID was not found

Body
{
    id: 1,
    name: "Dr. Y",
    phone: "(716) 716-7166",
    address: "Doctor Street, DC, 20052",
    title: "Primary Care Physician",
    notes: "Love this doc the most!",
    success: true
}

Delete a Doctor
DELETE/patients/{patientid}/doctors/{doctorid}

Remove information on a single doctor. The current user will need write access to the patient’s data.

Example URI

DELETE /patients/patientid/doctors/doctorid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

doctorid
integer (required) 

unique ID of the doctor (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_doctor_id (404) - a doctor with that ID was not found

Body
{
    id: 1,
    name: "Dr. X",
    phone: "(617) 617-6177",
    address: "Doctor Street, DC, 20052",
    notes: "Love this doc the most!",
    title: "Primary Care Physician",
    success: true
}

Pharmacies

Details for all pharmacies from whom the selected patient receives medication.

The address field is geocoded into the lat and lon fields.

Pharmacies Collection

Create a Pharmacy
POST/patients/{patientid}/pharmacies

Store details of a new pharmacy. The current user will need write access to the patient.

Example URI

POST /patients/patientid/pharmacies
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

name
string (required) 

name of the pharmacy

address
string (optional) 

Postal address of the pharmacy. Newlines can optionally be used to split lines.

phone
string (optional) 

contact phone number for the pharmacy

hours
dictionary (optional) 

The hours the pharmacy is open. Keys are full lowercase names of the days of the week (e.g., monday), and values are themselves dictionaries of the form {open: OPEN_TIME, close: CLOSE_TIME}, where times are formatted in the hh:MM a 12-hour format specified in ISO 8601. These hours should be in the local timezone of the patient.

notes
string (optional) 

freeform text notes about the pharmacy by the patient

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Pharmacy X",
    address: "Pharmacy Street, DC, 20052"
    phone: "(617) 617-6177",
    hours: {
        monday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        tuesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        wednesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        thursday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        friday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        saturday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        sunday: {
            open: "09:00 am",
            close: "05:00 pm"
        }
    },
    notes: "Great pharmacy! Love the smell"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • name_required (400) - a non-blank name must be provided

  • invalid_hours (400) - the opening/closing hours dictionary is not in the form specified above

Body
{
    id: 1,
    name: "Pharmacy X",
    address: "Pharmacy Street, DC, 20052"
    phone: "(617) 617-6177",
    hours: {
        monday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        tuesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        wednesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        thursday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        friday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        saturday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        sunday: {
            open: "09:00 am",
            close: "05:00 pm"
        }
    },
    lat: 50.9692224,
    lon: 0.0893951,
    notes: "Great pharmacy! Love the smell",
    success: true
}

Retrieve all Pharmacies
GET/patients/{patientid}/pharmacies

Get a list of all the patient’s pharmacies. Includes full information on each… The current user will need read access to the patient.

Example URI

GET /patients/patientid/pharmacies
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or name, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

name
string (optional) 

Filter results by name of pharmacy. Performs fuzzy matching.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

Body
{
    pharmacies: [
        {
            id: 1,
            name: "Pharmacy X",
            ...
        },
        ...
    ],
    count: 3,
    success: true
}

Pharmacy

Retrieve a Pharmacy
GET/patients/{patientid}/pharmacies/{pharmacyid}

View information on an individual pharmacy. The current user will need read access to the patient.

Example URI

GET /patients/patientid/pharmacies/pharmacyid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

pharmacyid
integer (required) 

unique ID of the pharmacy

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_pharmacy_id (404) - a pharmacy with that ID was not found

Body
{
    id: 1,
    name: "Pharmacy X",
    address: "Pharmacy Street, DC, 20052"
    phone: "(617) 617-6177",
    hours: {
        monday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        tuesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        wednesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        thursday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        friday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        saturday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        sunday: {
            open: "09:00 am",
            close: "05:00 pm"
        }
    },
    notes: "Great pharmacy! Love the smell",
    lat: 50.9692224,
    lon: 0.0893951,
    success: true
}

Change a Pharmacy's Info
PUT/patients/{patientid}/pharmacies/{pharmacyid}

Change information (name, phone, address and/or hours) of an individual pharmacy. The current user will need write access to the patient.

Example URI

PUT /patients/patientid/pharmacies/pharmacyid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

pharmacyid
integer (required) 

unique ID of the pharmacy (url)

name
string (optional) 

Name of the pharmacy. Must not be blank.

phone
string (optional) 

contact phone number for the pharmacy

address
string (optional) 

postal address, in the format specified in POST

hours
dictionary (optional) 

Opening/closing hours, in the format specified in POST. The dictionary can be partially empty.

notes
string (optional) 

freeform text notes about the pharmacy by the patient

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Pharmacy. Y",
    phone: "(716) 716-7166",
    address: "Pharmacy Street, DC, 20052",
    hours: {
        tuesday: {
            open: "10:00 am"
        }
    },
    notes: "Doesn't smell like it used to"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_hours (400) - the opening/closing hours dictionary is not in the form specified above in POST
  • invalid_pharmacy_id (404) - a pharmacy with that ID was not found

  • name_required (400) - the name cannot be changed to a blank name

Body
{
    id: 1,
    name: "Pharmacy Y",
    address: "Pharmacy Street, DC, 20052"
    phone: "(716) 716-7166",
    hours: {
        monday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        tuesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        wednesday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        thursday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        friday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        saturday: {
            open: "09:00 am",
            close: "05:00 pm"
        },
        sunday: {
            open: "09:00 am",
            close: "05:00 pm"
        }
    },
    notes: "Doesn't smell like it used to",
    lat: 50.9692224,
    lon: 0.0893951,
    success: true
}

Delete a Pharmacy
DELETE/patients/{patientid}/pharmacies/{pharmacyid}

Remove information on a single pharmacy. The current user will need write access to the patient.

Example URI

DELETE /patients/patientid/pharmacies/pharmacyid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

pharmacyid
integer (required) 

unique ID of the pharmacy (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_pharmacy_id (404) - a pharmacy with that ID was not found

Body
{
    id: 1,
    name: "Pharmacy X",
    ...,
    success: true
}

Medications

Data on regular medications a patient takes (either manually entered or retrieved via OAuth2 + FHIR from e.g., the DRE).

Medication data responses contain the number_left integer key: this is an estimation of the number of pills left based on fill_date and dose events submitted to the API. It will only be non-null if fill_date is non-null.

Permissions

Medications have custom permissions that are used instead of the patient-wide permissions. Each medication has access_anyone, access_family and access_prime fields, each of which can be set to read, write, default or none to control the access the relevant share group (anyone, family or prime) has to the medication.

read, write and none are self-explanatory, but default is slightly more complex:

  • For an anyone share, default gives the user read-only access

  • For a family share on an as-needed medication (including medications that are both regular and as-needed), default gives the user write access.

  • For a family share on a medication that is not as-needed (so is regular-only), default gives the user read-only access.

  • For a prime share, default delegates to the patient-level permissions: it first looks at any explicit permissions specified in the share itself, and if that’s set to default then it looks as access_prime in the patient data.

There is one exception to this rule. The user who creates a medication is recorded as the creator of that medication, and they always have write access to that medication (even if, for example, the patient is shared with the user through the anyone group and the medication has access_anyone="default" (which would usually give them read-only access), that user will still have write access).

All three keys (access_anyone, access_family and access_prime) default to default, the recommended permission structure.

Schedule

Various endpoints below take and output schedule data items, representing a regular schedule the patient should take a certain medication on. These are used to schedule reminders, and so are vitally important for the core of the app. The data format schedules must be in is precisely defined below, and must be followed exactly.

At it’s core, each schedule is an object.

It must contain the as_needed boolean key signifying whether the medication can be taken whenever needed (irregularly), and the regularly key signifying it should be taken on a regular schedule. At least one must be true. If regularly is false, no extra information is needed. If regularly is true, all of the following scheduling data is also required.

The schedule must have an until key signifying when the patient should stop taking the medication:

  • In Perpetuity (forever)
until: {
    type: "forever"
}
  • A certain number of times before stopping
until: {
    type: "number",
    stop: 5
}
  • Until a certain date
until: {
    type: "date",
    stop: "2015-05-07"
}

The schedule must have a frequency key signifying on which days the patient should take the medication. Specific times of each day can be set using the times key, which is described below. frequency is an object consisting of an n key and a unit key: n is a number representing that the medication should be taken every n units, and unit specifies that unit (it can be "day", "month" or "year" only).

frequency can also have an optional exclude key, denoting that the medication should sometimes be skipped. If present, exclude must be an object consisting of exclude and repeat keys. exclude is an array of numbers representing the indices of days that must be swapped (where the first day it should be taken on has index 0, the second day it should be taken on has index 1, etc). repeat is a number representing the length of the exclude cycle: in other words, indices are taken modulo this. See the examples below for illustration.

  • Daily
frequency: {
    n: 1,
    unit: "day"
}
  • Weekdays only
frequency: {
    n: 1,
    unit: "day",
    exclude: {
        exclude: [5, 6],
        repeat: 7
    }
}
  • Weekly
frequency: {
    n: 7,
    unit: "day"
}
  • Every 28 days
frequency: {
    n: 28,
    unit: "day"
}
  • Monthly
frequency: {
    n: 1,
    unit: "month"
}
  • Quarterly
frequency: {
    n: 3,
    unit: "month"
}
  • Quarterly apart from last quarter
frequency: {
    n: 3,
    unit: "month",
    exclude: {
        exclude: [3],
        repeat: 4
    }
}

frequency can also include a start key: a YYYY-MM-DD formatted (local) date representing any date that the medication was taken on (for example, the date the medication was started on). This means that, for example, Orange knows which day of the week a weekly medication is taken on. start can either be a string or an array of strings.

For example, a start array can be used to represent a medication that should be taken on the 1st and the 15th of every month

frequency: {
    n: 1,
    unit: "month",
    start: [
        "2015-01-01",
        "2015-01-15"
    ]
}

The schedule must also include a times key representing the times of the day the medication is taken on (i.e., frequency dictates which days and times dictates which times on those days). The number of times the medication is taken each day should not be explicitly specified, this is instead calculated from the length of times. times should be an array consisting of objects, each representing a time of the day at which the medication should be taken. There are 3 different types:

  • Any time of the day
{
    type: "unspecified"
}
  • An exact time (time should be formatted HH:MM a in local time)
{
    type: "exact",
    time: "09:00 am"
}
  • A time based on the user’s habits. event can be either "breakfast", "lunch", "dinner" or "sleep". when can be either "before" or "after".
{
    type: "event",
    event: "lunch",
    when: "before"
}

When sent to the API, each time will be given an ID that will be returned in all endpoints returning the medication schedule. These IDs can be used in the /medications/:medicationid/times/:timeid endpoint to set notification settings on a user-specific basis for that specific time in that specific medication schedule.

The schedule must also include a take_with_food key. This is a boolean specifying whether or not the medication must be taken with food. true means it must be taken with food, false means it must not be taken with food, and null means it does not matter. Note that false means the medication must not be taken with food, not that it just doesn’t matter. So if unknown, take_with_food should be null.

Finally the schedule must include take_with_medications and take_without_medications keys. These should be arrays of integers that are the IDs of medications with which this medication must (or must not) be taken simultaneously with. If there are no medications like this, they should both be [].

Note that each medication object is also returned from the API with schedule_summary string field, containing human-readable text representing the schedule the medication should be taken on (e.g,. "Daily until 7/30/15"). schedule_summary will not denote whether the medication is as-needed unless it is as-needed only, in which case it will say "As needed only".

Medications Collection

Create a new Medication
POST/patients/{patientid}/medications

Store details of a new medication the patient has started taking. The current user must have write access to the patient.

If origin="imported" and import_id is set, then the API will look for an existing medication with the same import_id. If one exists then it will be updated with the specified details, rather than a new medication created. This can be used to merge medication details when running an import process in the app multiple times.

Example URI

POST /patients/patientid/medications
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

name
string (required) 

human-formatted name of the medication

rx_norm
string (optional) 

rxNorm ID code for the medication

ndc
string (optional) 

NDC ID code for the medication

dose
dictionary (optional) 

Dose of medication the patient should take. Formatted as {quantity: QUANTITY, unit: UNIT} where QUANTITY is numeric and UNIT is a string (e.g., "mg")

route
string (optional) 

ROA of medication

form
string (optional) Example: pill
rx_number
string (optional) 

RX control number of the prescription

fill_date
string (optional) 

ISO 8601 YYYY-MM-DD in local time of the last date the medication was filled

quantity
integer (optional) 

number of medication in each ‘pack’

type
string (optional) 

legal medication type: e.g., "OTC"

brand
string (optional) 

brand name of medication

origin
string (optional) 

Optional string containing the source the medication data came from. Suggested use case would be to store either "manual" or "imported" in this field for each medication, although note that no backend API validation is done of this field so any string value can be set.

import_id
integer (optional) 

Optional integer representing a unique ID for an imported medication in the imported data source (for example, the id field in the DRE/another FHIR API). If a medication with the same import_id value already exists, and origin="imported", then the existing medication will be updated with the new info, rather than a new medication created.

schedule
dictionary (optional) 

a schedule datum in the form described above

access_prime
string (optional) 

The access permissions users in the prime group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

access_family
string (optional) 

The access permissions users in the family group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

access_anyone
string (optional) 

The access permissions users in the anyone group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

doctor_id
integer (optional) 

ID of the doctor prescribing the patient’s medication. This doctor must already exist in /patients/:patientid/doctors

pharmacy_id
integer (optional) 

ID of the pharmacy selling the patient’s medication. This doctor must already exist in /patients/:patientid/doctors

notes
string (optional) 

Optional freeform notes field for the medication.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Loratadine",
    rx_norm: "324026",
    ndc: "33261-0228",
    dose: {
        quantity: 100,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: false,
        regularly: true,
        until: { type: "forever" },
        frequency: { n: 1, unit: "day" },
        times: [
            { type: "event", event: "breakfast", when: "before" },
            { type: "event", event: "breakfast", when: "after" },
            { type: "event", event: "lunch", when: "before" },
            { type: "event", event: "lunch", when: "after" },
            { type: "event", event: "dinner", when: "before" },
            { type: "event", event: "dinner", when: "after" },
            { type: "event", event: "sleep", when: "before" },
            { type: "event", event: "sleep", when: "after" },
            { type: "exact", time: "09:00" },
            { type: "exact", time: "21:30" },
            { type: "unspecified" }
        ],
        take_with_food: null,
        take_with_medications: [],
        take_without_medications: []
    },
    access_anyone: "default",
    access_family: "default",
    access_prime: "default",
    doctor_id: 1,
    pharmacy_id: 1,
    notes: "Love this med!!"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • name_required (400) - medication must have a non-blank name

  • invalid_dose (400) - medication dose specified in the format specified above

  • invalid_quantity (400) - quantity not a positive integer

  • invalid_fill_date (400) - fill date is not a YYYY-MM-DD date

  • invalid_schedule (400) - schedule is not specified in the format specified above

  • invalid_access_anyone (400) - the access_anyone field, if passed, must be either read, write, default or none

  • invalid_access_family (400) - the access_family field, if passed, must be either read, write, default or none

  • invalid_access_prime (400) - the access_prime field, if passed, must be either read, write, default or none

  • invalid_doctor_id (400) - a doctor with that ID was not found

  • invalid_pharmacy_id (400) - a pharmacy with that ID was not found

  • invalid_import_id (400) - the import_id value was invalid (must be undefined, null or an integer)

Body
{
    id: 1,
    name: "Loratadine",
    rx_norm: "324026",
    ndc: "33261-0228",
    dose: {
        quantity: 100,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    number_left: 17,
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: false,
        regularly: true,
        until: { type: "forever" },
        frequency: { n: 1, unit: "day" },
        times: [
            { id: 1, type: "event", event: "breakfast", when: "before" },
            { id: 2, type: "event", event: "breakfast", when: "after" },
            { id: 3, type: "event", event: "lunch", when: "before" },
            { id: 4, type: "event", event: "lunch", when: "after" },
            { id: 5, type: "event", event: "dinner", when: "before" },
            { id: 6, type: "event", event: "dinner", when: "after" },
            { id: 7, type: "event", event: "sleep", when: "before" },
            { id: 8, type: "event", event: "sleep", when: "after" },
            { id: 9, type: "exact", time: "09:00" },
            { id: 10, type: "exact", time: "21:30" },
            { id: 11, type: "unspecified" }
        ],
        take_with_food: null,
        take_with_medications: [],
        take_without_medications: []
    },
    schedule_summary: "Daily",
    access_anyone: "default",
    access_family: "default",
    access_prime: "default",
    doctor_id: 1,
    pharmacy_id: 1,
    notes: "Love this med!!",
    success: true
}

Retrieve all Medications
GET/patients/{patientid}/medications

Get a list of all the patient’s medications. Includes full information on each, but doctor and pharmacy details are not expanded out. To get a successful response from this endpoint, the current user must have read access to the patient. Further, only medications for which the current user has read access will be returned.

To view medications for all patient logs the user has access to (rather than just one specific patient), make this request to GET /medications. That endpoint accepts exactly the same parameters as this one.

Example URI

GET /patients/patientid/medications
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or name, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

name
string (optional) 

Filter results by name of medication. Performs fuzzy matching.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

Body
{
    medications: [
        {
            id: 1,
            name: "Loratadine",
            rx_norm: "324026",
            ndc: "33261-0228",
            dose: {
                quantity: 100,
                unit: "mg"
            },
            route: "oral",
            form: "pill",
            rx_number: "123456789",
            fill_date: "2015-05-01",
            number_left: 17,
            quantity: 50,
            type: "OTC",
            brand: "Claritin",
            origin: "manual",
            schedule: {
                as_needed: false,
                regularly: true,
                until: { type: "forever" },
                frequency: { n: 1, unit: "day" },
                times: [
                    { id: 1, type: "event", event: "breakfast", when: "before" },
                    { id: 2, type: "event", event: "breakfast", when: "after" },
                    { id: 3, type: "event", event: "lunch", when: "before" },
                    { id: 4, type: "event", event: "lunch", when: "after" },
                    { id: 5, type: "event", event: "dinner", when: "before" },
                    { id: 6, type: "event", event: "dinner", when: "after" },
                    { id: 7, type: "event", event: "sleep", when: "before" },
                    { id: 8, type: "event", event: "sleep", when: "after" },
                    { id: 9, type: "exact", time: "09:00" },
                    { id: 10, type: "exact", time: "21:30" },
                    { id: 11, type: "unspecified" }
                ],
                take_with_food: null,
                take_with_medications: [],
                take_without_medications: []
            },
            schedule_summary: "Daily",
            access_anyone: "default",
            access_family: "default",
            access_prime: "default",
            doctor_id: 1,
            pharmacy_id: 1,
            notes: "Love this med!!"
        },
        ...
    ],
    count: 7,
    success: true
}

Medication

Retrieve a Medication
GET/patients/{patientid}/medications/{medicationid}

View information on an individual medication. Doctor and pharmacy details are expanded out. The current user must have read access to both the patient and the medication.

Example URI

GET /patients/patientid/medications/medicationid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

medicationid
integer (required) 

unique ID of the medication

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_medication_id (404) - a medication with that ID was not found

Body
{
    id: 1,
    name: "Loratadine",
    rx_norm: "324026",
    ndc: "33261-0228",
    dose: {
        quantity: 100,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    number_left: 17,
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: false,
        regularly: true,
        until: { type: "forever" },
        frequency: { n: 1, unit: "day" },
        times: [
            { id: 1, type: "event", event: "breakfast", when: "before" },
            { id: 2, type: "event", event: "breakfast", when: "after" },
            { id: 3, type: "event", event: "lunch", when: "before" },
            { id: 4, type: "event", event: "lunch", when: "after" },
            { id: 5, type: "event", event: "dinner", when: "before" },
            { id: 6, type: "event", event: "dinner", when: "after" },
            { id: 7, type: "event", event: "sleep", when: "before" },
            { id: 8, type: "event", event: "sleep", when: "after" },
            { id: 9, type: "exact", time: "09:00" },
            { id: 10, type: "exact", time: "21:30" },
            { id: 11, type: "unspecified" }
        ],
        take_with_food: null,
        take_with_medications: [],
        take_without_medications: []
    },
    schedule_summary: "Daily",
    access_anyone: "default",
    access_family: "default",
    access_prime: "default",
    doctor: {
        id: 1,
        name: "Dr. Y",
        phone: "(716) 716-7166",
        address: "Doctor Street, DC, 20052",
        notes: "Love this doc the most!",
        success: true
    },
    pharmacy: {
        name: "Pharmacy X",
        address: "Pharmacy Street, DC, 20052"
        phone: "(617) 617-6177",
        hours: {
            monday: {
                open: "0900",
                close: "1700"
            },
            tuesday: {
                open: "0900",
                close: "1700"
            },
            wednesday: {
                open: "0900",
                close: "1700"
            },
            thursday: {
                open: "0900",
                close: "1700"
            },
            friday: {
                open: "0900",
                close: "1700"
            },
            saturday: {
                open: "0900",
                close: "1700"
            },
            sunday: {
                open: "0900",
                close: "1700"
            },
            notes: "Great pharmacy! Love the smell"
        },
        notes: "Love this med!!"
    },
    success: true
}

Change a Med's Info
PUT/patients/{patientid}/medications/{medicationid}

Change information (all keys apart from id) of an individual medication. The current user must have read access to the patient and write access to the medication.

Example URI

PUT /patients/patientid/medications/medicationid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

medicationid
integer (required) 

unique ID of the medication (url)

name
string (optional) 

human-formatted name of the medication

rx_norm
string (optional) 

rxNorm ID code for the medication

ndc
string (optional) 

NDC ID code for the medication

dose
dictionary (optional) 

As in POST. A whole new dictionary must be sent.

route
string (optional) 

ROA of medication

form
string (optional) Example: pill
rx_number
string (optional) 

RX control number of the prescription

fill_date
string (optional) 

ISO 8601 YYYY-MM-DD in local time of the last date the medication was filled

quantity
integer (optional) 

number of medication in each ‘pack’

type
string (optional) 

legal medication type: e.g., "OTC"

brand
string (optional) 

brand name of medication

origin
string (optional) 

Place the data for this medication came from (suggested use case: store either "manual" or "imported" in this field, although the API does no validation of the string contents)

import_id
integer (optional) 

The original ID of the medication in the data source it was imported from. Updating import_id here will not cause any merges, but when new medications are created at the POST endpoint they will compare to the updated import_id value.

schedule
dictionary (optional) 

As in POST. A whole new schedule must be sent.

access_prime
string (optional) 

The access permissions users in the prime group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

access_family
string (optional) 

The access permissions users in the family group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

access_anyone
string (optional) 

The access permissions users in the anyone group should have to this medication, overriding the patient-wide permissions. Must be either read, write, none or default. Defaults to default.

doctor_id
integer (optional) 

ID of the doctor prescribing the patient’s medication

pharmacy_id
integer (optional) 

ID of the pharmacy selling the patient’s medication

notes
string (optional) 

freeform notes field for the medication.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    name: "Fexofenadine",
    rx_norm: "12345",
    ndc: "1234-6789",
    dose: {
        quantity: 120,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: true,
        regularly: false
    },
    access_anyone: "write",
    access_family: "write",
    access_prime: "write",
    doctor_id: 1,
    pharmacy_id: 1,
    notes: "Great!"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • name_required (400) - medication must have a non-blank name

  • invalid_dose (400) - medication dose specified in the format specified above

  • invalid_quantity (400) - quantity not a positive integer

  • invalid_fill_date (400) - fill date is not a YYYY-MM-DD date

  • invalid_schedule (400) - schedule is not specified in the format specified above

  • invalid_access_anyone (400) - the access_anyone field, if passed, must be either read, write, default or none

  • invalid_access_family (400) - the access_family field, if passed, must be either read, write, default or none

  • invalid_access_prime (400) - the access_prime field, if passed, must be either read, write, default or none

  • invalid_doctor_id (400) - a doctor with that ID was not found

  • invalid_pharmacy_id (400) - a pharmacy with that ID was not found

  • invalid_import_id (400) - the import_id value was invalid (must be undefined, null or an integer)

Body
{
    id: 1,
    name: "Fexofenadine",
    rx_norm: "12345",
    ndc: "1234-6789",
    dose: {
        quantity: 120,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    number_left: 17,
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: true,
        regularly: false
    },
    access_anyone: "write",
    access_family: "write",
    access_prime: "write",
    doctor_id: 1,
    pharmacy_id: 1,
    notes: "Great!",
    success: true
}

Delete a Medication
DELETE/patients/{patientid}/medications/{medicationid}

Remove a single medication. The current user must have read access to the patient and write access to the medication.

Example URI

DELETE /patients/patientid/medications/medicationid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

medicationid
integer (required) 

unique ID of the medication (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_medication_id (404) - a medication with that ID was not found

Body
{
    id: 1,
    name: "Loratadine",
    rx_norm: "324026",
    ndc: "33261-0228",
    dose: {
        quantity: 100,
        unit: "mg"
    },
    route: "oral",
    form: "pill",
    rx_number: "123456789",
    fill_date: "2015-05-01",
    number_left: 17,
    quantity: 50,
    type: "OTC",
    brand: "Claritin",
    origin: "manual",
    schedule: {
        as_needed: false,
        regularly: true,
        until: { type: "forever" },
        frequency: { n: 1, unit: "day" },
        times: [
            { id: 1, type: "event", event: "breakfast", when: "before" },
            { id: 2, type: "event", event: "breakfast", when: "after" },
            { id: 3, type: "event", event: "lunch", when: "before" },
            { id: 4, type: "event", event: "lunch", when: "after" },
            { id: 5, type: "event", event: "dinner", when: "before" },
            { id: 6, type: "event", event: "dinner", when: "after" },
            { id: 7, type: "event", event: "sleep", when: "before" },
            { id: 8, type: "event", event: "sleep", when: "after" },
            { id: 9, type: "exact", time: "09:00" },
            { id: 10, type: "exact", time: "21:30" },
            { id: 11, type: "unspecified" }
        ],
        take_with_food: null,
        take_with_medications: [],
        take_without_medications: []
    },
    schedule_summary: "Daily",
    access_anyone: "write",
    access_family: "write",
    access_prime: "write",
    doctor_id: 1,
    pharmacy_id: 1,
    notes: "Great!",
    success: true
}

Medication Time

This endpoint represents a single ‘abstract’ time at which the schedule indicates a medication should be taken: i.e., one item in the times array of a medication. This endpoint should be used to both view and set the notification settings for this specific medication time, both at a a default user-wide level (the default key) and specifically for this user (not patient) (the user key).

Both keys represent an ‘offset’: the number of minutes before the medication should be scheduled at which the user should be notified they need to take the med. For example, if user = 5 and default = 30 then the current user will get a notification 5 minutes before the med should be taken, and all other users (unless they have set their own notification settings) will get a notification 30 minutes before. Values will default to 30 minutes before.

The user key can be the string default to represent that that user has not set a custom offset and the default should be respected.

Both the user and/or default key can be the string paused to represent that the user has paused notification for that medication (but is still taking the medication, they just don’t want to receive notifications about it).

View Notification Settings
GET/patients/{patientid}/medications/{medicationid}/times/{timeid}

View the current notification settings for the current user and the global user-wide default

Example URI

GET /patients/patientid/medications/medicationid/times/timeid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

medicationid
integer (required) 

unique ID of the medication

timeid
integer (required) 

unique ID of the medication time

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_medication_id (404) - a medication with that ID was not found

  • invalid_time_id (404) - a time with that ID was not found for that medication

Body
{
    default: 30,
    user: "default",
    success: true
}

Set Notification Settings
PUT/patients/{patientid}/medications/{medicationid}/times/{timeid}

Set the current notification settings for the current user and the global user-wide default

Example URI

PUT /patients/patientid/medications/medicationid/times/timeid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (*url)

medicationid
integer (required) 

unique ID of the medication (*url)

timeid
integer (required) 

unique ID of the medication time (*url)

default
number (optional) 

number of minutes to change the notification offset to for all users who haven’t set a custom value, or "paused" to disable notifications

user
number or string (optional) 

number of minutes to change the notification offset to for this user, or "default" to indicate that the default value should be used, or "paused" to disable notifications

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    default: 20,
    user: 15
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_medication_id (404) - a medication with that ID was not found

  • invalid_time_id (404) - a time with that ID was not found for that medication

  • invalid_default (400) - invalid default value (must be a positive number)

  • invalid_user (400) - invalid user value (must be a positive number or "default")

Body
{
    default: 20,
    user: 15,
    success: true
}

Dose Events

A dose event is when the patient takes their medication (either when they’re supposed to, adhering, or not, non-adhering) or skips their medication.

Dose Events Collection

Create an Event
POST/patients/{patientid}/doses

Store details of a new dose event (e.g., when a patient signifies they’ve taken their medication or skipped it). The current user will need write access to both the patient and the medication.

Example URI

POST /patients/patientid/doses
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

medication_id
integer (required) 

unique ID of the medication for which the patient has adhered

date
string (required) Example: 2015-05-31T19:27:09+00:00
dose
dictionary (optional) 

Dose of medication the patient should take. Formatted as {quantity: QUANTITY, unit: UNIT} where QUANTITY is numeric and UNIT is a string (e.g., "mg")

ISO 8601 combined date-time in UTC representing the date and time at which the patient took the medication

taken
boolean (required) 

Boolean representing whether the user took their medication (i.e., true if they took it, false if this dose event represents them skipping their medication)

scheduled
integer (optional) 

Integer representing the ID of a schedule event corresponding to the patient taking their medication. These are the same IDs used to set notification settings at the /patients/{patientid}/medications/{medicationid}/times/{timeid} endpoints. If this is not set for a dose, the matcher will assume the medication was taken for an unspecified schedule event or was taken out of schedule (as would be the case normally with an as_needed medication).

notes
string (optional) 

free-text field for things such as observations and reactions recorded by the patient

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    medication_id: 1,
    date: "2015-05-31T19:27:09+00:00",
    taken: true,
    scheduled: 3,
    notes: "Feeling sleepy now!"
}
Response  201
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • invalid_date (400) - the date field specified is not in valid ISO 8601 format

  • invalid_medication_id (400) - no medication with the specified ID can be found

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • taken_required (400) - a value is not specified (it should be a boolean) for taken

  • invalid_taken (400) - taken is not a valid boolean

  • invalid_scheduled (400)

    scheduled is not a valid integer corresponding to an event with that ID in the schedule for the medication (with ID medication_id)

Body
{
    id: 1,
    medication_id: 1,
    date: "2015-05-31T19:27:09+00:00",
    notes: "Feeling sleepy now!",
    taken: true,
    scheduled: 3,
    success: true
}

Retrieve all Doses
GET/patients/{patientid}/doses

Get a list of all dose events for the patient. Includes full information on each, but medication_id is not expanded out into medication. To get a successful response from this endpoint, the user will need read access to the patient. Further, only dose events for which the user has read access to the medication will be shown.

Example URI

GET /patients/patientid/doses
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

limit
integer (optional) 

Maximum number of results to return. Defaults to 25. Set to 0 to return all results.

offset
integer (optional) 

Number of initial results to ignore (used in combination with limit) for pagination. Defaults to 0.

sort_by
string (optional) 

Field to sort results by. Must by either id or date, and defaults to id.

sort_order
string (optional) 

The order to sort results by: either asc or desc. Defaults to asc.

start_date
string (optional) 

Restrict results to events that took place after this date. Must be a valid ISO 8601 datetime. Defaults to 0.

end_date
string (optional) 

Restrict results to events that took place before this date. Must be a valid ISO 8601 datetime. Defaults to infinity.

medication_id
integer (optional) 

Restrict results to events for this medication. Must correspond to a medication owned by the current patient. Defaults to not filtering by medication.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_limit (400) - the specified result limit is invalid

  • invalid_offset (400) - the specified result offset is invalid

  • invalid_sort_by (400) - the specified sort field is invalid

  • invalid_sort_order (400) - the specified sort order is invalid

  • invalid_start_date (400) - the specified start date is an invalid ISO 8601 datetime

  • invalid_end_date (400) - the specified end date is an invalid ISO 8601 datetime

  • invalid_medication_id (400) - the medication ID specified to sort by is invalid

Body
{
    doses: [
        {
            id: 1,
            medication_id: 1,
            date: "2015-05-31T19:27:09+00:00",
            taken: true,
            scheduled: 3,
            notes: "Feeling sleepy now!"
        },
        ...
    ],
    count: 46,
    success: true
}

Dose Event

Retrieve One Event
GET/patients/{patientid}/doses/{doseid}

View information on an individual dose event. medication_id is helpfully expanded out into medication. The current user will need read access to both the patient and the dose event.

Example URI

GET /patients/patientid/doses/doseid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

doseid
integer (required) 

unique ID of the dose

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_dose_id (404) - a dose with that ID was not found

Body
{
    id: 1,
    date: "2015-05-31T19:27:09+00:00",
    notes: "Feeling sleepy now!",
    taken: true,
    scheduled: 3,
    medication: {
        id: 1,
        name: "Loratadine",
        rx_norm: "324026",
        ndc: "33261-0228",
        dose: {
            quantity: 100,
            unit: "mg"
        },
        route: "oral",
        form: "pill",
        rx_number: "123456789",
        quantity: 50,
        type: "OTC",
        schedule: {
            ...
        },
        doctor_id: 1,
        pharmacy_id: 1,
        success: true
    },
    success: true
}

Change an Event
PUT/patients/{patientid}/doses/{doseid}

Change information (medication, date and/or notes) of a single dose event. The current user will need write access to the patient, the old medication, and the new medication (if different).

Example URI

PUT /patients/patientid/doses/doseid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

doseid
integer (required) 

unique ID of the dose (url)

medication_id
integer (optional) 

ID of a medication to change the dose to. Must correspond to an existing medication.

date
string (optional) 

new ISO 8601 datetime to change the date of the dose to

taken
boolean (required) 

Boolean representing whether the user took their medication (i.e., true if they took it, false if this dose event represents them skipping their medication)

scheduled
integer (optional) 

Number representing the ID of the scheduled dose event. See POST endpoint documentation for full details. Send null to remove an existing value.

notes
string (optional) 

String to change the notes field of the dose to. If blank, will save the notes field blank correspondingly.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Body
{
    medication_id: 1,
    date: "2015-05-31T19:27:09+00:00",
    taken: true,
    scheduled: 3,
    notes: "Not sleepy from this - forgot I took a melatonin pill earlier!"
}
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_dose_id (404) - a dose with that ID was not found

  • invalid_date (400) - the date field specified is not in valid ISO 8601 format

  • invalid_medication_id (400) - no medication with the specified ID can be found

  • invalid_taken (400) - taken is not a valid boolean

  • invalid_scheduled (400)

    scheduled is not a valid integer corresponding to an event with that ID in the schedule for the medication (with ID medication_id)

Body
{
    id: 1,
    medication_id: 1,
    date: "2015-05-31T19:27:09+00:00",
    taken: true,
    scheduled: 3,
    notes: "Not sleepy from this - forgot I took a melatonin pill earlier!",
    success: true
}

Delete an Event
DELETE/patients/{patientid}/doses/{doseid}

Remove a single dose event (this will update generated statistics correspondingly, so be careful!) The current user will need write access to both the patient and the medication.

Example URI

DELETE /patients/patientid/doses/doseid
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient (url)

doseid
integer (required) 

unique ID of the dose (url)

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have write access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_dose_id (404) - a dose event with that ID was not found

Body
{
    id: 1,
    medication_id: 1,
    date: "2015-05-31T19:27:09+00:00",
    taken: true,
    scheduled: 3,
    notes: "Feeling sleepy now!"
    success: true
}

First Dose Event

Retrieve first date medication (Dose) was taken
GET/patients/{patientid}/doses/nonempty/first

Get date of first dose taken by a patient.

Example URI

GET /patients/patientid/doses/nonempty/first
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

Body
{
    min_dose_date: "2015-04-01T15:29:09.000-04:00",
    count: 46,
    success: true
}

Schedule

Schedule

View Schedule
GET/patients/{patientid}/schedule

Given that all medication data (including schedules in the required format) have been entered, this endpoint generates an easy-to-use schedule for when the patient should take their medication over a specific date range.

If events are in the past, the schedule will contain a took_medication boolean indicating whether the patient took the medication when they were required. If they did, then a delay integer field will be present indicating the number of minutes late the patient was when taking the medication. delay is signed: if the patient took the medication too early, it will be negative.

Each event item can be one of two types: time and date. time items represent a specific datetime at which the medication should be taken (and are formatted as an ISO-8601 datetime in the patient’s local timezone). date items indicate that the medication can be taken at any time on the specified day, and have the date formatted as YYYY-MM-DD in the patient’s local timezone.

Each event will also contain a happened boolean key indicating whether it took place in the past (true) or will take place in the future (false).

Crucially, each event contains a notification key containing an ISO-8601 datetime in the patient’s local timezone representing the time at which the patient should be notified they need to take their medication. This uses the user-specific notification settings set in the /patients/:patientid/medications/:medicationid/times/:timeid endpoints (and defaults to 30 minutes prior).

The schedule also contains “as needed” events, where a dose was recorded manually by the user not corresponding to any scheduled event. To distinguish between these and scheduled events, a scheduled key is included: it is not present for “as needed” events, and is present and equal to the ID of the scheduled time event for scheduled events.

Additionally, each event will contain the take_with_food (boolean or null), take_with_medications (array of integers) and take_without_medications (array of integers) keys, each representing the same data and formatted the same way as in the medication schedule field.

The schedule will also contain an overall statistics object, containing floats took_medication (a mean average value for took_medication as a percentage out of 100), delta (a mean average value of all of the delays) and delay (a mean average value of the absolute values of all the delays). Each number in statistics will be null if there are no schedule events in the past found (for example, if start date is in the future). As needed events are ignored when calculating statistics.

The user will need read access to the patient to get a successful response from this endpoint. Further, only schedule events corresponding to medications for which the user has read access will be shown.

To view the schedule for all patient logs the user has access to (rather than just one specific patient), make this request to GET /schedule. That endpoint accepts exactly the same start_date and end_date parameters as this one, although it ignores any specified medication_id parameter.

Example URI

GET /patients/patientid/schedule
URI Parameters
HideShow
patientid
integer (required) 

unique ID of the patient

start_date
string (optional) 

Start schedule at this date. Must be a valid ISO 8601 YYYY-MM-DD date. Defaults to the current time.

end_date
string (optional) 

End schedule at this date. Must be a valid ISO 8601 YYYY-MM-DD date. Defaults to exactly one week later than the current time.

medication_id
integer (optional) 

Restricts the schedule to events for one medication only.

Request
HideShow
Headers
Authorization: Bearer ACCESS_TOKEN
Response  200
HideShow

Errors

  • access_token_required (401) - no access token specified in Authorization header

  • invalid_access_token (401) - the access token specified is invalid

  • unauthorized (403) - the current user does not have read access to this patient

  • invalid_patient_id (404) - a patient with the specified ID was not found

  • invalid_medication_id (400) - a medication with that ID was not found

  • invalid_start (400) - a start date not formatted correctly as YYYY-MM-DD

  • invalid_end (400) - an end date not formatted correctly as YYYY-MM-DD

Body
// This illustrates a response when the current date falls somewhere
// in the middle of the specified date range. In other cases, either
// the first or second type of schedule datums would of course not be present.
{
    schedule: [
        {
            type: "time",
            date: "2015-03-31T19:27:09+00:00",
            notification: "2015-03-31T18:57:09+00:00",
            medication_id: 1,
            took_medication: true,
            delay: -17,
            dose_id: 14,
            take_with_food: true,
            take_with_medications: [1],
            take_without_medications: [3]
        },
        {
            type: "time",
            date: "2015-03-31T19:27:09+00:00",
            notification: "2015-03-31T18:57:09+00:00",
            medication_id: 1,
            took_medication: false,
            take_with_food: null,
            take_with_medications: [],
            take_without_medications: []
        },
        {
            type: "time",
            date: "2015-03-31T19:27:09+00:00",
            notification: "2015-03-31T18:57:09+00:00",
            medication_id: 1,
            took_medication: false,
            take_with_food: null,
            take_with_medications: [],
            take_without_medications: []
        },
        ... // more events that have already taken place
        {
            type: "time",
            date: "2015-05-31T19:27:09+00:00",
            notification: "2015-03-31T18:57:09+00:00",
            medication_id: 1,
            take_with_food: null,
            take_with_medications: [],
            take_without_medications: []
        },
        {
            // no time specified, just the date
            type: "date",
            date: "2015-05-31",
            notification: "2015-03-31T18:57:09+00:00",
            medication_id: 3,
            take_with_food: null,
            take_with_medications: [],
            take_without_medications: []
        },
        ... // more events in the future
    ],
    // only present if some events have already taken place
    statistics: {
        took_medication: 70.3,
        delay: 4,
        delta: -1
    },
    success: true
}

NPI

Uses the BloomAPI to look up provider information in the National Plan and Provider Enumeration System (NPPES).

Provider Collection

Get NPI Data
GET/npi/{npi}

Searches BloomAPI using then provided NPI. Returns the data associated with that NPI if it exists.

Example URI

GET /npi/npi
URI Parameters
HideShow
npi
string (required) 

10 digit NPI number

Response  200
HideShow
  • bloom_error (500) - error communicating with Bloom API
Body
{
    business_address: {
        address_details_line: "2ND FLOOR",
        address_line: "2350 W EL CAMINO REAL",
        city: "MOUNTAIN VIEW",
        country_code: "US",
        state: "CA",
        zip: "940406203"
    },
    credential: "MD",
    enumeration_date: "2006-08-31T00:00:00.000Z",
    first_name: "HARRY",
    gender: "male",
    last_name: "DENNIS",
    last_update_date: "2012-01-10T00:00:00.000Z",
    npi: 1073624029,
    practice_address: {
        address_line: "795 EL CAMINO REAL",
        city: "PALO ALTO",
        country_code: "US",
        phone: "6508532992",
        state: "CA",
        zip: "943012302"
    },
    provider_details: [{
        healthcare_taxonomy_code: "208000000X",
        license_number: "G68571",
        license_number_state: "CA",
        taxonomy_switch: "yes"
    }],
    sole_proprietor: "no",
    type: "individual"
}

Provider Collection

Query Providers
POST/npi

Searches BloomAPI using a combination of first name, last name and State (two letter code). Receives an array of possible Prescriber matches. BloomAPI limits the response to 100 possible matches.

Example URI

POST /npi
URI Parameters
HideShow
search
object (required) 

Query object to search by. See example below, as well as here and here for documentation.

Request
HideShow
Body
{
    name: [{
        first: "Harry", //String, Optional
        last: "Dennis" //String, required
    }],
    address: [{
        state: "CA" //String, optional
    }]
}
Response  200
HideShow
  • rxnorm_error (500) - error communicating with Bloom API
Body
{
    providers: [ 
        {
            business_address: {
                address_details_line: "2ND FLOOR",
                address_line: "2350 W EL CAMINO REAL",
                city: "MOUNTAIN VIEW",
                country_code: "US",
                state: "CA",
                zip: "940406203"
            },
            credential: "MD",
            enumeration_date: "2006-08-31T00:00:00.000Z",
            first_name: "HARRY",
            gender: "male",
            last_name: "DENNIS",
            last_update_date: "2012-01-10T00:00:00.000Z",
            npi: 1073624029,
            practice_address: {
                address_line: "795 EL CAMINO REAL",
                city: "PALO ALTO",
                country_code: "US",
                phone: "6508532992",
                state: "CA",
                zip: "943012302"
            },
            provider_details: [{
                healthcare_taxonomy_code: "208000000X",
                license_number: "G68571",
                license_number_state: "CA",
                taxonomy_switch: "yes"
            }],
            sole_proprietor: "no",
            type: "individual"
        },
        ...
    ],
    count: 3,
    success: true
}

RXNorm

Uses the RXNorm and OpenFDA APIs to look up medication details. An example flow would be to search by name using the /group endpoint. If no results are found, then search for spelling suggestions using the /spelling endpoint, and use the results to search by the correct name using the /group endpoint.

Medications by Name

Query
POST/rxnorm/group

Searches rxnorm for drug by name. Receives a response object with the name searched for and arrays of information. Possible matches for drugs (if any) are located in the response.drugGroup.conceptGroup array, with the bulk of the information in response.drugGroup.conceptGroup[].conceptProperties.

Example URI

POST /rxnorm/group
URI Parameters
HideShow
medname
string (required) 

Medication name to search by.

Request
HideShow
Body
{
    medname: "Allegra-D"
}
Response  200
HideShow
  • rxnorm_error (500) - error communicating with Bloom API
Body
{
    result: {
        drugGroup: {
            name: "Allegra-D",
            conceptGroup: [
                {
                    tty: "BPCK"
                },
                {
                    tty: "SBD",
                    conceptProperties: [
                        {
                            rxcui: "997512",
                            name: "12 HR Fexofenadine hydrochloride 60 MG / Pseudoephedrine Hydrochloride 120 MG Extended Release Oral Tablet [Allegra-D]",
                            synonym: "Allegra-D 12 Hour (fexofenadine hydrochloride 60 MG / pseudoephedrine hydrochloride 120 MG) Extended Release Oral Tablet",
                            tty: "SBD",
                            language: "ENG",
                            suppress: "N",
                            umlscui: "C0716180",
                            dfg: ["Oral Tablet"],
                            brand: "Allegra-D",
                            modifiedname: "12 HR Fexofenadine hydrochloride 60 MG / Pseudoephedrine Hydrochloride 120 MG Extended Release  "
                        }, {
                            rxcui: "997515",
                            name: "24 HR Fexofenadine hydrochloride 180 MG / Pseudoephedrine Hydrochloride 240 MG Extended Release Oral Tablet [Allegra-D]",
                            synonym: "Allegra-D 24 Hour (fexofenadine hydrochloride 180 MG / pseudoephedrine hydrochloride 240 MG) Extended Release Oral Tablet",
                            tty: "SBD",
                            language: "ENG",
                            suppress: "N",
                            umlscui: "C1616745",
                            dfg: ["Oral Tablet"],
                            brand: "Allegra-D",
                            modifiedname: "24 HR Fexofenadine hydrochloride 180 MG / Pseudoephedrine Hydrochloride 240 MG Extended Release  "
                        }
                    ]
                }
            ]
        },
        compiled: [
            {
                rxcui: "997512",
                name: "12 HR Fexofenadine hydrochloride 60 MG / Pseudoephedrine Hydrochloride 120 MG Extended Release Oral Tablet [Allegra-D]",
                synonym: "Allegra-D 12 Hour (fexofenadine hydrochloride 60 MG / pseudoephedrine hydrochloride 120 MG) Extended Release Oral Tablet",
                tty: "SBD",
                language: "ENG",
                suppress: "N",
                umlscui: "C0716180",
                dfg: ["Oral Tablet"],
                brand: "Allegra-D",
                modifiedname: "12 HR Fexofenadine hydrochloride 60 MG / Pseudoephedrine Hydrochloride 120 MG Extended Release  "
            },
            {
                rxcui: "997515",
                name: "24 HR Fexofenadine hydrochloride 180 MG / Pseudoephedrine Hydrochloride 240 MG Extended Release Oral Tablet [Allegra-D]",
                synonym: "Allegra-D 24 Hour (fexofenadine hydrochloride 180 MG / pseudoephedrine hydrochloride 240 MG) Extended Release Oral Tablet",
                tty: "SBD",
                language: "ENG",
                suppress: "N",
                umlscui: "C1616745",
                dfg: ["Oral Tablet"],
                brand: "Allegra-D",
                modifiedname: "24 HR Fexofenadine hydrochloride 180 MG / Pseudoephedrine Hydrochloride 240 MG Extended Release  "
            }
        ],
        dfg: ["Oral Tablet"],
        brand: ["Allegra-D"]
    },
    success: true
}

Medications by Spelling

Query
POST/rxnorm/spelling

Searches RXNorm for spelling suggestions for a given medication.

Example URI

POST /rxnorm/spelling
URI Parameters
HideShow
medname
string (required) 

Medication name to search by.

Request
HideShow
Body
{
    medname: "allegrad"
}
Response  200
HideShow
  • rxnorm_error (500) - error communicating with Bloom API
Body
{
    result: {
        suggestionGroup: {
            name: "allegrad",
            suggestionList: {
                suggestion: ["Allegra-D", "Allegra", "Allermax", "Alera", "Alkeran", "Aloeguard"]
            }
        }
    },
    success: true
}

Generated by aglio on 10 May 2018