Wiki

Clone wiki

Cinch Web / 04 API

API Communication

Version 3 of the API communication has tried to generacize the objects sent and received as much as possible so that any application utilizing the API can save and retrieve data in the whatever way it sees fit without breaking any of the needed relationships between the data classes. There are a few specific examples where a specialized API call is needed in order to ensure the needed object is created properly; specifically for creating a new product or patient.

Every API call is looking for the authid and password of the user as part of the JSON body to the API post; if it's missing or incorrect the API will return a 'not logged in' error.
Note: authid users email or username NOT user_id

Authentication has changed


The login has changed.

The login request is at the BASE api:

cinch.wellinks.com/api/login

In order to secure the proper authentication tokens and current api version base url you must first sign in your user (either doctor or patient), taking the username (or email) and password once clicked --- they become the username / password as part of an HTTP_BASIC_AUTHENTICATION header -- in this scenario these become hashed from a (username:password) format:

Authorization Basic ZG9jdG9yQHRlc3QuY29tOnBhc3N3b3Jk

and via a GET request to cinch.wellinks.com/api/login -- if the login was successful, you should get a json response like the following:

    {
      "authorization": "QGpmj8",
      "auth_token": "9d105ff6a9956b40",
      "api_version": "v3",
      "api_path": "/api/v3/",
      "role": "patient",
      "id": 386,
      "characteristic": "AAAA",
      "service": "1234",
      "time_zone": null,
      "terms_agreed": "https://localhost:3000/terms"
    }

In this scenario from every point on there the api version / base api to call from the api itself. Also is the current user's role and id for any subsequent requests.

The auth_token becomes X-Auth-Token and authorization becoes X-Authorization:

X-Authorization: QGpmj8
X-Auth-Token: 9d105ff6a9956b40

Bluetooth Characteristic and Service UUID

Please not that we're now passing down the chacteristic and service (see above) as they are about to change to a 128bit version


Terms and Conditions

A user must agree to the terms and conditions in order to be able to use the application. When a user signs up via the website they agree to the terms and conditions upon account creation; but when an orthotist creates the account the user cannot agree to the terms and conditions immediately and these must be presented upon first login. When a user logs in via the app the return will have a terms_agreed parameter (see above); if the terms returns 'true' that means the user has agreed to the terms and never has to be presented with the terms and conditions again. If however the terms_agreed parameter is a string url, that url will be the url to pull and display into a web ui for accepting and submitting to the backend:

    {
      "authorization": "QGpmj8",
      "auth_token": "9d105ff6a9956b40",
      "api_version": "v3",
      "api_path": "/api/v3/",
      "role": "patient",
      "id": 386,
      "characteristic": "AAAA",
      "service": "1234",
      "time_zone": null,
      "terms_agreed": "https://cinch.wellinks.com/terms"
    }

In order to save that the user has agreed to the terms and conditions the generic save_object endpoint can be used to save that the user agrees:

    {
      "class": "Patient",
      "rel_id": 386,
      "data": {
        "terms_agreed": true
      }
    }

Selection

The base api url is also used from the response - so to hit select you'd use cinch.wellinks.com/api/v3/select as based upon the api_path in the login response object. Everything else as described below would also live at the returned api_path.

Once a login object / authentication token is received, the current user object would be needed. In order to get the current user object a request to SELECT with the class being the returned class (in this case Doctor) and the id either being an empty array or the id of the user would get you the current user object; there is now no need to send authid ad password in the json body:

{
  "class": "Doctor",
  "id": "[2]"
}

or

{
  "class": "Doctor",
  "id": "[]"
}

Would return the current user, Doctor id 2. The objects are being thinned out as requested, so the Doctor object is no longer carrying all the Patient objects in the patient list, only what is necessary to display the patient list:

{
  "role": "doctor",
  "id": 2,
  "firstname": "",
  "lastname": "",
  "email": "doctor@test.com",
  "product_styles": [
    {
      "id": 1,
      "name": "Rigo",
      "description": ""
    },
    {
      "id": 2,
      "name": "Boston",
      "description": ""
    }
  ],
  "base_products": [
    {
      "id": 4,
      "name": "Boston calibration",
      "description": "",
      "style_id": 2,
      "sensor_locations": {
        "middle": 2,
        "lower": 3
      },
      "product_feedbacks": {}
    },
    {
      "id": 3,
      "name": "Rigo 1 strap brace",
      "description": "",
      "style_id": 1,
      "sensor_locations": {
        "middle": 2
      },
      "product_feedbacks": {
        "light": 1,
        "vibration": 2
      }
    }
  "patients": [
    {
      "role": "patient",
      "id": 52,
      "treatment_start": "03/20/2017 -  2:05 PM",
      "displayname": "34"
    },
    {
      "role": "patient",
      "id": 23,
      "treatment_start": "",
      "displayname": "10"
    },
    {
      "role": "patient",
      "id": 25,
      "treatment_start": "",
      "displayname": "30"
    }
  ]
}

In order to get the deeper Patient object, upon tapping a Patient entry a request to /api/v3/select will need to be made with the Patient class / id as described below


Time Zone

    https://cinch.wellinks.com/api/v3/time_zone

    {"time_zone": "America/New_York"}

The time_zone endpoint expects a simple JSON object with a valid timezone ID sent, and will respond with either a 200 / empty JSON object or an error with a status 422.

The use of this endpoint will vary depending on the logic scenario: Upon login (above) the time_zone will be returned in the json object.

a) if the time_zone is null, then the phone's time_zone will be sent without interaction from the user.

b) if the time_zone is not null but different than the current phone's time_zone, the user will be asked if they wish to change their time zone (if yes, the time_zone will be sent to the api; if not, ignored).

c) if the time_zone is the same as the phone's current time_zone, nothing further needs to be done.


Select Object

    http://cinch.wellinks.com/api/v3/select

    {"class":"Patient", "id":[8]}

The select object call merely asks for a JSON representation of an object from the database based upon the class and id of that object. This will only return the object that is a subset of that user. Meaning, as a doctor I can ONLY view patients that are already attached to me; I cannot view Patient with id 33 if I am not already treating Patient 33.

As both Doctor and Patient if I send a request for my user class with my id or an empty array for id I will only see myself.

As a Doctor if I send a request for a patient not under my care I will get a Patient not found response.

Sending an empty array is asking for all the objects under the current user. So, for example if as a Doctor I send:

{"class":"Patient", "id":[]}

A list of all the Patient objects under that doctor will be returned.

Multiple object of a class can be returned by id:

{"class":"Patient", "id":[1,2,8]}

Would return three Patient objects.
Note: if any id sent up is not under that Doctor's care that object will not be returned but other valid objects will be returned. If Patient 2 is not under this current Doctor's care Patient 1 and Patient 8 will be returned.

If a request for all objects of a lower nature - say sensors -- is requested, an array across patients/products/sensors will be returned, so generally an empty id array is not what is wanted, rather requesting specific objects based upon an id already in memory -- basically, drilling down the data -- is what is desired.

######JSON Response:######

Depends on what is being requested; multiple class types are allowed to be requested. If the current user is not allowed to view the requested information either an {error: 'Patient not found'} will be returned.


Daily Summaries

    http://cinch.wellinks.com/api/v3/dailysummary

NOTE the format for dailysummary has changed; it uses both POST and GET.

For both doctor and patient this call requests the saved daily summaries of sensor events for a given product id. In order to GET the listing of dailysummaries, request the dailysummary by appending the product id:

    http://cinch.wellinks.com/api/v3/dailysummary/8

######JSON Response:###### A listing of daily summary objects from treatment to today will be sent back with each entry having 3 data points: compliance_hours required (the amount the brace should be worn), compliance_hours (how many hours the device was worn at the correct tightness), and the actual_hours_worn (the length the brace was worn).

    {
      "Records": [
       {
          "compliance_hours_required": 5.0,
          "compliance_hours": 0.0,
          "actual_hours_worn": 0.0,
          "offHours": 0.0,
          "unknownHours": 24.0,
          "log_date": "06/22/2017",
          "encouragement": "There was no brace-wear logged for today. If there is a problem with the brace, let your parents or orthotist know. ",
          "manual": false
        },
        {
          "compliance_hours_required": 5.0,
          "compliance_hours": 1.5,
          "actual_hours_worn": 3.75,
          "offHours": 9.0,
          "unknownHours": 11.25,
          "log_date": "06/21/2017",
          "encouragement": "You've almost reached the right amount of time, try pulling the straps a little bit tighter tomorrow if you can. If the brace hurts or pinches when you tighten it, let your parents or orthotist know. ",
          "manual": false
        },
        {
          "compliance_hours_required": 5.0,
          "compliance_hours": 1.5,
          "actual_hours_worn": 7.5,
          "offHours": 16.5,
          "unknownHours": 0.0,
          "log_date": "06/20/2017",
          "encouragement": "You did a good job reaching your wear-time goal! Tomorrow, try wearing the brace a little tighter when you put it on. If the brace hurts or pinches when you tighten it, let your parents or orthotist know. ",
          "manual": false
        },
        {
          "compliance_hours_required": 5.0,
          "compliance_hours": 4.75,
          "actual_hours_worn": 5.5,
          "offHours": 18.5,
          "unknownHours": 0.0,
          "log_date": "06/19/2017",
          "encouragement": "You're doing great! Tomorrow, try wearing the brace a little tighter when you put it on.",
          "manual": false
        }
      ]
    }

Saving a Daily Summary

We are now allowing a user of our application without our sensors to track their wear time by adding their daily summaries in manually; in order to SAVE a daily summary, a POST will be sent to the base /dailysummary endpoint in this format:

{
  "action": "add",
  "product_id": "1333",
  "date": "2017-08-20",
  "hours": "3.5"
}

Delete a DailySummary

Note this will ONLY work on a dailysummary that is set to be manual; this will NOT work on dailysummaries that are auto-generated. POST to the /dailysummary endpoint as such; again, sending multiple dates will delete all if they are under that product.

{
  "action": "delete",
  "product_id": "1333",
  "dates": [
    "2017-08-21",
    "2017-08-20"
  ]
}

Sync Device Data

    http://cinch.wellinks.com/api/v3/datadump

NOTE: this still needs to keep the data root object to work

    {"data": {"product_id": "30", "location": "1",  "serial": "123456", "records": []}}

For the patient this pushes the sensor events read by the bluetooth communication into a data object paramater packaged with the product_id and location enum of the given sensor.

######JSON Response:######


Create Patient

    http://cinch.wellinks.com/api/v3/create_patient

Patients need to be created with email address and birthday (birthday format can take mm/dd/yyyy or yyyy-mm-dd formats). Gender can be "male", "female" or "other".

    {
      "firstname":"Davis", 
      "lastname":"Smith", 
      "email":"davis@test.con", 
      "username":"Davis ", 
      "password":"password",
    "gender": "male",
    "birthday": "1980-01-16"
    }

######JSON Response:###### In response a base patient will be sent back:

    {
      "role": "patient",
      "id": 76,
      "firstname": "Davis",
      "lastname": "Smith",
      "email": "davis@test.con",
      "birthday": null,
      "username": "Davis ",
      "treatment_start": "",
      "products": [],
      "parents": []
    }

Search For Patient

    http://cinch.wellinks.com/api/v3/search_patient

Only a doctor can search for a patient; sending both the email and birthday in a POST.

    {
      "email": "patient@example.com",
      "birthday": "2005-09-10"
    }

######JSON Response:###### In response you will get an error message wtih no match (or problems with the birthday, etc) or patient object:

        [
          {
            "role": "patient",
            "id": 386,
            "firstname": "Schafer",
            "lastname": "Boys",
            "email": "the.schafer.boys@gmail.com",
            "birthday": "2011-10-09",
            "treatment_start": "2017-08-22T14:48:10-04:00",
            "time_zone": null,
            "web_sign_up": true,
            "support_links": [
              {
                "title": "About Wellinks",
                "url": "http://www.wellinks.com"
              },
              {
                "title": "Email Support",
                "url": "mailto:support@wellinks.com?subject=Cinch%20Support"
              }
            ],
            "products": [
              {
                "id": 1333,
                "base_product_id": 5,
                "base_product_name": "Boston 3 Strap",
                "base_product_sensor_count": 3,
                "active": true,
                "passkey": null,
                "feedback_states": [
                  {
                    "name": "light",
                    "value": 1,
                    "active": false
                  },
                  {
                    "name": "vibration",
                    "value": 2,
                    "active": false
                  }
                ],
                "active_feedback": {},
                "patient_id": 386,
                "treatment": {
                  "id": 1330,
                  "product_id": 1333,
                  "start": "2017-08-22T14:48:10-04:00",
                  "end": null,
                  "summary": null,
                  "prescriptions": {
                    "id": 595,
                    "prescription_date": "2017-08-22T14:48:10-04:00"
                  },
                  "latest_prescription": {
                    "id": 595,
                    "hours": 10,
                    "summary": null,
                    "prescription_date": "2017-08-22T14:48:10-04:00",
                    "prescribed_tensions": []
                  }
                },
                "sensors": []
              }
            ],
            "parents": []
          }
        ]

Add or Delete Existing Patients To A Doctor

    http://cinch.wellinks.com/api/v3/doctor_patient

Only a doctor can connect or remove patients to that doctor; removing the connection of a patient does NOT delete the patient.

    {
      "action": "add",
      "ids": [
        386, 175
      ]
    }

######JSON Response:###### You will receive an array of the patient objects which ids have been connected:

    [
      {
        "role": "patient",
        "id": 386,
        "firstname": "Schafer",
        "lastname": "Boys",
        "email": "the.schafer.boys@gmail.com",
        "birthday": "2011-10-09",
        "treatment_start": "2017-08-22T14:48:10-04:00",
        "time_zone": null,
        "web_sign_up": true,
        "support_links": [
          {
            "title": "About Wellinks",
            "url": "http://www.wellinks.com"
          },
          {
            "title": "Email Support",
            "url": "mailto:support@wellinks.com?subject=Cinch%20Support"
          }
        ],
        "products": [
          {
            "id": 1333,
            "base_product_id": 5,
            "base_product_name": "Boston 3 Strap",
            "base_product_sensor_count": 3,
            "active": true,
            "passkey": null,
            "feedback_states": [
              {
                "name": "light",
                "value": 1,
                "active": false
              },
              {
                "name": "vibration",
                "value": 2,
                "active": false
              }
            ],
            "active_feedback": {},
            "patient_id": 386,
            "treatment": {
              "id": 1330,
              "product_id": 1333,
              "start": "2017-08-22T14:48:10-04:00",
              "end": null,
              "summary": null,
              "prescriptions": {
                "id": 595,
                "prescription_date": "2017-08-22T14:48:10-04:00"
              },
              "latest_prescription": {
                "id": 595,
                "hours": 10,
                "summary": null,
                "prescription_date": "2017-08-22T14:48:10-04:00",
                "prescribed_tensions": []
              }
            },
            "sensors": []
          }
        ],
        "parents": []
      }
    |
    }

Create Product

    http://cinch.wellinks.com/api/v3/create_product

To create a product the data params must contain the patient_id, the model of product by the base_product_id (as part of the doctor response passing back the base_products to choose from), a generated 6 digit passkey, and an array of the chosen locations based upon the possible sensor locations also as part of the base_products originally sent to the doctor:

    {
        "patient_id":75, 
        "base_product_id":2, 
        "passkey"=>905891, 
        "locations":[1, 3]
    }

######JSON Response:###### The response if successful is a product object to be inserted into that current patient.products:

    {
      "id": 100,
      "base_product_id": 2,
      "active": true,
      "passkey": "654321",
      "feedback_states": [
        {
          "name": "light",
          "value": 1,
          "active": false
        },
        {
          "name": "vibration",
          "value": 2,
          "active": false
        }
      ],
      "active_feedback": {},
      "patient_id": 76,
      "treatment": {
        "id": 78,
        "product_id": 100,
        "start": "01/27/2017 -  2:53 PM",
        "end": null,
        "summary": null,
        "prescriptions": [],
        "latest_prescription": null
      },
      "sensors": [
        {
          "id": 196,
          "serial": null,
          "active": true,
          "location": 1,
          "location_string": "upper",
          "last_event_id": 0,
          "missing_event_ids": []
        },
        {
          "id": 197,
          "serial": null,
          "active": true,
          "location": 3,
          "location_string": "lower",
          "last_event_id": 0,
          "missing_event_ids": []
        }
      ]
    }

Save Object

    /http://cinch.wellinks.com/api/v3/save_object

Can be used in a generic fashion to save specific data attributed to an object -- it will unfold attributes and if valid or applicable, save a new such class object to the database. Used specifically to save sensors found to the backend as part of a product:

    {
    "class":"Sensor", 
    "rel_id":195, 
    "data":{"serial":"2327450425230b"}
}

In the example above the serial was saved as part of a sensor model by setting the class to Sensor with the 'related id' (ie rel_id) of 195 and passing along the data object with a serial paramater. Any viable class and data with applicable paramaters would work.

######JSON Response:######

The response will be a serialized version of the class saved; in this case a Sensor model:

    {
      "serial": "2327450425230b",
      "product_id": 99,
      "location": 3,
      "id": 195,
      "model": null,
      "created_at": "2017-01-27T14:46:54.534-05:00",
      "updated_at": "2017-01-27T14:57:33.359-05:00",
      "active": true
    }

Edit / Save relationship

Paramaters are changed depending if the object in question is added or deleted:

    http://cinch.wellinks.com/api/v3/edit_relationship

    {
        "relationship":"patient", 
        "focus_id":2,
        "focus_class": 
        "doctor", 
        "rel_ids":[51], 
        "action": "add"
    }

In the example above a doctor is adding an existing patient to his patient list based upon the action add. After the regular authid and password to verify the doctor account, the data object holds the necessary information:

The relationship is set as patient with the rel_ids array set to the id of the patient (multiple ids can be set).

In order for the for the change in relationship to work, a focus_class and focus_id must also be passed along -- in this case the current doctor and the doctor's id is set as focus_id; any object that has a relation could be used (ie sensor to product); in this case it just happens to be the doctor very same doctor class. Multiple ids of the same object could be used (ie removing multiple sensor objects attributed to a product).

To delete the relationship between a doctor and patient -- removing the patient from the patient list (but not deleting from the database) one would send the same but change the action to delete:

    { 
        "relationship":"patient", 
        "focus_id":2,
        "focus_class": "doctor", 
        "rel_ids":[51], 
        "action": "delete"
    }

######JSON Response:######

The actual object being updated will be sent back -- in this case the same entire doctor object that was sent for the verification process.


Create Prescription

Sent specifically after connecting to the devices via bluetooth and requesting a calibration (CCM) or basing a new prescription upon the current prescription (but in that case only changing the wear hours) the necessary data object must include the product_id, the hours to wear, and multiple prescribed_tensions, one for each sensor attributed to that object. The prescribed_tensions should include the sensor_id, the sensor location enum, then the force and position as read by the either the current or past calibration

{
    "product_id":99, 
    "hours":14, 
    "prescribed_tensions":
        [
        {"sensor_id":194, "location":1, "force":92, "position":0}, 
        {"sensor_id":195, "location":3, "force":4, "position":10}
        ]
}

######JSON Response:######

The response will again be a proper serialized prescription object with both the prescription id and the date:

    {
      "id": 54,
      "hours": 14,
      "summary": null,
      "prescription_date": "2017-01-27",
      "prescribed_tensions": [
        {
          "id": 100,
          "force": 92,
          "position": 0,
          "location": 1,
          "location_string": "upper"
        },
        {
          "id": 101,
          "force": 4,
          "position": 10,
          "location": 3,
          "location_string": "lower"
        }
      ]
    }

Curves

    http://cinch.wellinks.com/api/v3/curve

Curves have their own endpoint for listing, adding and deleting a curve entry; in order to list a curve sending a GET to the endpoint will get a list of curves and curve entries of that patient, as well as the vertebrae breakdown for saving new curves:

#####JSON Response#####

{  "curves": [
    {
      "name": "A",
      "points": [
        {
          "id": 7,
          "name": "A",
          "angle": 30,
          "direction": "left",
          "top": "C1",
          "bottom": "C4",
          "risser": 3,
          "sanders": 8,
          "date": "2017-05-23T01:52:00.589-04:00"
        },
        {
          "id": 9,
          "name": "A",
          "angle": 22,
          "direction": "right",
          "top": "C3",
          "bottom": "C5",
          "risser": null,
          "sanders": null,
          "date": "2017-05-25T01:56:00.656-04:00"
        },
        {
          "id": 15,
          "name": "A",
          "angle": 30,
          "direction": "left",
          "top": "C1",
          "bottom": "C4",
          "risser": 5,
          "sanders": 3,
          "date": "2017-05-23T16:07:58.301-04:00"
        }
      ],
      "color": "FE6A4F"
    },
    {
      "name": "B",
      "points": [
        {
          "id": 8,
          "name": "B",
          "angle": 0,
          "direction": "right",
          "top": "C5",
          "bottom": "C6",
          "risser": null,
          "sanders": null,
          "date": "2017-05-23T01:52:56.107-04:00"
        }
      ],
      "color": "35859F"
    },
    {
      "name": "C",
      "points": [
        {
          "id": 11,
          "name": "C",
          "angle": 3,
          "direction": "right",
          "top": "C4",
          "bottom": "C7",
          "risser": null,
          "sanders": null,
          "date": "2017-05-26T01:57:08.078-04:00"
        },
        {
          "id": 14,
          "name": "C",
          "angle": 30,
          "direction": "left",
          "top": "C1",
          "bottom": "C4",
          "risser": 5,
          "sanders": 3,
          "date": "2017-05-23T16:07:31.141-04:00"
        }
      ],
      "color": "A5E948"
    }
  ],
  "vertebrae": [
    "C1","C2","C3","C4","C5","C6","C7","T1","T2","T3","T4","T5","T6","T7","T8","T9","T10","T11","T12","L1","L2","L3","L4","L5"
  ]
}

}

Saving a Curve

To save a curve, send a POST to the same /curve endpoint with the action as save and the additional curve data:

    {
      "action": "add",
      "data": {
        "date": "2017-08-20",
        "top": "C2",       <---- choice made from the vertebrae list
        "bottom": "C5",
        "angle": 30,
        "direction": "right",  <----  right or left
        "risser": 5,
        "sanders": 3,
        "patient_id": 77,  <---- the current patient_id
        "name": "A"  <--- sending the name adds this curve entry to that colleciton.
      }

If no date is sent, then the curent time will be set as the date. If no name is sent at all, then the next possible alphabet will be added as the name. If an id of an already existing curve is sent it will update that curve. Also note that a valid curve's top vertebrae must be above a bottom vertebrae in a curve (ie not flipping the values like top:: C4 bottom: C2.

Deleting a Curve

To delete a saved curve, the same /curve endpoint is used, but the action is now delete with the curve ID being sent as data; more than one curve can be deleted.

{
  "action": "delete",
  "ids": [
    167
  ]
}

Appointments

    http://cinch.wellinks.com/api/v3/appointment

Appointments also have their own endpoint for listing, adding and deleting an entry. Appointments are similar to curves with some additional logic in order to construct a new valid appointment. In order to list the future appointtments, sending a GET to the endpoint will get a list of entries of upcoming (future) appointments as well as the needed appointment_types and appointment_prompt_ids.

#####JSON Response#####

        {
      "appointments": [
        {
          "id": 4,
          "alert_types": {},
          "alert_seen": false,
          "notes": "These are notes as string.",
          "doctor": "One, Orthotist",
          "doctor_id": 7,
          "date": "2017-08-30T12:30:00 -0400"
        },
        {
          "id": 1,
          "alert_types": {},
          "alert_seen": false,
          "notes": "Here are some notes for NO doctor",
          "doctor": "",
          "doctor_id": null,
          "date": "2017-09-01T14:00:00 -0400"
        },
        {
          "id": 13,
          "alert_types": {
            "app": 0,
            "email": 1
          },
          "alert_seen": false,
          "notes": "These are notes as string.",
          "doctor": "One, Orthotist",
          "doctor_id": 7,
          "date": "2017-09-20T10:30:00 -0400"
        },
        {
          "id": 2,
          "alert_types": {},
          "alert_seen": false,
          "notes": "This one HAS a doctor",
          "doctor": "One, Orthotist",
          "doctor_id": 7,
          "date": "2017-10-01T14:00:00 -0400"
        }
      ],
      "appointment_types": [
        {
          "id": 1,
          "title": "Default Type 1",
          "description": "Just a default description",
          "prompt_ids": [
            1,
            2,
            3
          ]
        },
        {
          "id": 2,
          "title": "Default Type 2",
          "description": "Another description",
          "prompt_ids": [
            1,
            2
          ]
        },
        {
          "id": 3,
          "title": "Not a default Type",
          "description": "Not default",
          "prompt_ids": [
            1,
            3
          ]
        }
      ],
      "appointment_prompts": [
        {
          "id": 1,
          "text": "Default prompt text 1"
        },
        {
          "id": 2,
          "text": "Default prompt 2"
        },
        {
          "id": 3,
          "text": "Not a default prompt"
        }
      ]
    }

Saving an Appointment

Hitting the same /appointment endpoint with a POST and your appointment data will save an appointment. Now, the 'notes' of an appointment is the joining of all the appointment_prompt texts into one string (as a user could enter in their own notes); but the chosen appointment_prompt ids should also be passed along (merely for tracking how often each prompt is being used). The doctor_id is NOT required to save an appointment, but if the doctor_id is passed along as well, the appointment can be saved with a specific doctor:

    {
  "action": "add",
  "data": {
    "date": "2017-9-20 10:30",
    "appointment_type_id": 1,
    "notes": "These are notes as string.",
    "patient_id": 178,
    "doctor_id": 7,
    "appointment_prompt_ids": [
      1,
      2,
      3
    ],
    "alert_types": [
      "app",
      "email"
    ]
  }
}

You can update the alert_seen flag by hitting the same endpoint with the appointment id as a rel_id entry:

{
      "action": "add",
      "rel_id": 11,
      "data": {
        "alert_types": [
          "app",
          "email"
        ],
        "alert_seen": true
      }
    }

Deleting an Appointment

To delete a saved appointment, the same /appointment endpoint is used, but the action is now delete with the appointment IDs to be deleted sent in an array; multiple appointments can be deleted

{
  "action": "delete",
  "ids": [
    7, 8
  ]
}

Setting multiple appointments to seen

Use the same /appointment endpoint with the action now seen with the appointment IDs to be set in an array:

{
  "action": "seen",
  "ids": [
    7, 8
  ]
}

Following is no longer used; just keeping for history / data


Verify User

    http://cinch.wellinks.com/api/v3/verify

    {"authid":"Bob", "password":"password"}

The authid can either be the email, username or id of a user; depending on what is the relevant class / role (ie patient, parent or doctor) the responding JSON on a successful login will be different. If the user is a patient, they will get a JSON representation of their user complete with product which holds sensor and treatment / prescription data.
If the user is a doctor the returning JSON will contain a list of patients and basic base_products to create and assign new products to new and existing patients.

######JSON Response:######

The responding JSON will have the [role] of the logging in user; if the user is a patient the response will be a patient object which includes the current product with sensor information:

    {
      "role": "patient",
      "id": 5,
      "firstname": "Adam",
      "lastname": "Adam",
      "email": "adam@example.com",
      "birthday": null,
      "username": "Adam",
      "treatment_start": "01/25/2017 -  4:40 PM",
      "products": [
        {
          "id": 7,
          "base_product_id": 1,
          "active": true,
          "passkey": "231399",
          "feedback_states": [
            {
              "name": "light",
              "value": 1,
              "active": false
            },
            {
              "name": "vibration",
              "value": 2,
              "active": false
            }
          ],
          "active_feedback": {},
          "patient_id": 5,
          "treatment": {
            "id": 7,
            "product_id": 7,
            "start": "01/25/2017 -  4:40 PM",
            "end": null,
            "summary": null,
            "prescriptions": [
              {
                "id": 7,
                "hours": 14,
                "summary": null,
                "prescription_date": "2017-01-25",
                "prescribed_tensions": [
                  {
                    "id": 13,
                    "force": 25,
                    "position": 50,
                    "location": 2,
                    "location_string": "middle"
                  }
                ]
              }
            ],
            "latest_prescription": {
              "id": 7,
              "hours": 14,
              "summary": null,
              "prescription_date": "2017-01-25",
              "prescribed_tensions": [
                {
                  "id": 13,
                  "force": 25,
                  "position": 50,
                  "location": 2,
                  "location_string": "middle"
                }
              ]
            }
          },
          "sensors": [
            {
              "id": 13,
              "serial": "39b94302281c1b",
              "active": true,
              "location": 2,
              "location_string": "middle",
              "last_event_id": 240,
              "missing_event_ids": [
                "51 51",
                "52 52",
                "53 53",
                "54 54",
                "55 55",
                "56 56",
                "57 57",
                "58 58",
                "59 59",
                "60 60"
              ]
            }
          ]
        }
      ],
      "parents": []
    }

If the user logging in is a doctor they will receive a listing of the available base_products as well as a list of repeating patient information -- ie multiple patients broken down with data such as the above patient data information.

    {
      "role": "doctor",
      "id": 1,
      "firstname": "",
      "lastname": "",
      "email": "doctor@example.com",
      "product_styles": [
        {
          "id": 1,
          "name": "Rigo",
          "description": ""
        },
        {
          "id": 2,
          "name": "Boston",
          "description": ""
        }
      ],
      "base_products": [
        {
          "id": 1,
          "name": "Rigo 1 Strap",
          "description": "",
          "style_id": 1,
          "sensor_locations": {
            "middle": 2
          },
          "product_feedbacks": {
            "light": 1,
            "vibration": 2
          }
        },
        {
          "id": 2,
          "name": "Rigo 2 Strap",
          "description": "",
          "style_id": 1,
          "sensor_locations": {
            "upper": 1,
            "lower": 3
          },
          "product_feedbacks": {
            "light": 1,
            "vibration": 2
          }
        },
        {
          "id": 3,
          "name": "Rigo 3 Strap",
          "description": "",
          "style_id": 1,
          "sensor_locations": {
            "upper": 1,
            "middle": 2,
            "lower": 3
          },
          "product_feedbacks": {
            "light": 1,
            "vibration": 2
          }
        }
      ],
      "patients": [
        {
          "role": "patient",
          "id": 4,
          "firstname": "One",
          "lastname": "Test",
          "email": "test1@example.com",
          "birthday": null,
          "username": "Test1",
          "treatment_start": "01/25/2017 -  2:12 PM",
          "products": [
            {
              "id": 6,
              "base_product_id": 3,
              "active": true,
              "passkey": "485119",
              "feedback_states": [
                {
                  "name": "light",
                  "value": 1,
                  "active": true
                },
                {
                  "name": "vibration",
                  "value": 2,
                  "active": true
                }
              ],
              "active_feedback": {
                "light": 1,
                "vibration": 2
              },
              "patient_id": 4,
              "treatment": {
                "id": 6,
                "product_id": 6,
                "start": "01/25/2017 -  2:12 PM",
                "end": null,
                "summary": null,
                "prescriptions": [
                  {
                    "id": 9,
                    "hours": 14,
                    "summary": null,
                    "prescription_date": "2017-01-25",
                    "prescribed_tensions": [
                      {
                        "id": 14,
                        "force": 36,
                        "position": 42,
                        "location": 1,
                        "location_string": "upper"
                      },
                      {
                        "id": 15,
                        "force": 24,
                        "position": 59,
                        "location": 3,
                        "location_string": "lower"
                      }
                    ]
                  },
                  {
                    "id": 8,
                    "hours": 14,
                    "summary": null,
                    "prescription_date": "2017-01-25",
                    "prescribed_tensions": []
                  },
                  {
                    "id": 6,
                    "hours": 14,
                    "summary": null,
                    "prescription_date": "2017-01-25",
                    "prescribed_tensions": [
                      {
                        "id": 11,
                        "force": 66,
                        "position": 56,
                        "location": 1,
                        "location_string": "upper"
                      },
                      {
                        "id": 12,
                        "force": 77,
                        "position": 43,
                        "location": 3,
                        "location_string": "lower"
                      }
                    ]
                  },
                  {
                    "id": 5,
                    "hours": 14,
                    "summary": null,
                    "prescription_date": "2017-01-25",
                    "prescribed_tensions": [
                      {
                        "id": 9,
                        "force": 74,
                        "position": 100,
                        "location": 1,
                        "location_string": "upper"
                      },
                      {
                        "id": 10,
                        "force": 87,
                        "position": 100,
                        "location": 3,
                        "location_string": "lower"
                      }
                    ]
                  }
                ],
                "latest_prescription": {
                  "id": 9,
                  "hours": 14,
                  "summary": null,
                  "prescription_date": "2017-01-25",
                  "prescribed_tensions": [
                    {
                      "id": 14,
                      "force": 36,
                      "position": 42,
                      "location": 1,
                      "location_string": "upper"
                    },
                    {
                      "id": 15,
                      "force": 24,
                      "position": 59,
                      "location": 3,
                      "location_string": "lower"
                    }
                  ]
                }
              },
              "sensors": [
                {
                  "id": 11,
                  "serial": "2327450622230b",
                  "active": true,
                  "location": 1,
                  "location_string": "upper",
                  "last_event_id": 494,
                  "missing_event_ids": [
                    "0 0"
                  ]
                },
                {
                  "id": 12,
                  "serial": "2327450519260b",
                  "active": true,
                  "location": 3,
                  "location_string": "lower",
                  "last_event_id": 501,
                  "missing_event_ids": [
                    "0 0"
                  ]
                }
              ]
            }
          ],
          "parents": []
        },
        {
          "role": "patient",
          "id": 5,
          "firstname": "Adam",
          "lastname": "Adam",
          "email": "adam@example.com",
          "birthday": null,
          "username": "Adam",
          "treatment_start": "01/25/2017 -  4:40 PM",
          "products": [
            {
              "id": 7,
              "base_product_id": 1,
              "active": true,
              "passkey": "231399",
              "feedback_states": [
                {
                  "name": "light",
                  "value": 1,
                  "active": false
                },
                {
                  "name": "vibration",
                  "value": 2,
                  "active": false
                }
              ],
              "active_feedback": {},
              "patient_id": 5,
              "treatment": {
                "id": 7,
                "product_id": 7,
                "start": "01/25/2017 -  4:40 PM",
                "end": null,
                "summary": null,
                "prescriptions": [
                  {
                    "id": 7,
                    "hours": 14,
                    "summary": null,
                    "prescription_date": "2017-01-25",
                    "prescribed_tensions": [
                      {
                        "id": 13,
                        "force": 25,
                        "position": 50,
                        "location": 2,
                        "location_string": "middle"
                      }
                    ]
                  }
                ],
                "latest_prescription": {
                  "id": 7,
                  "hours": 14,
                  "summary": null,
                  "prescription_date": "2017-01-25",
                  "prescribed_tensions": [
                    {
                      "id": 13,
                      "force": 25,
                      "position": 50,
                      "location": 2,
                      "location_string": "middle"
                    }
                  ]
                }
              },
              "sensors": [
                {
                  "id": 13,
                  "serial": "39b94302281c1b",
                  "active": true,
                  "location": 2,
                  "location_string": "middle",
                  "last_event_id": 240,
                  "missing_event_ids": [
                    "51 51",
                    "52 52",
                    "53 53",
                    "54 54",
                    "55 55",
                    "56 56",
                    "57 57",
                    "58 58",
                    "59 59",
                    "60 60"
                  ]
                }
              ]
            }
          ],
          "parents": []
        }
        [......  etc .....]
      ]
    }

Updated