Node.js 6+ is required. The server relies on some ES6 subtleties (like destructuring assignments). We recommend you to use nvm, in order to juggle between many node version. Once you have it, just run:
nvm use
User configuration can be set in config/config.js
. Make a copy of config/config.template.js
and follow instructions in the file.
The server is actually composed of 2 processes:
app.js
is the main application implementing the REST API described below.push_sender.js
is responsible for sending the push notifications from a 0mq queue created byapp.js
.
You just need to run npm start
. This should run both processes. Of course you
need to run npm i
first to install dependencies.
A text-based data browser is provided in data/browser
. You can read more
information from the README file in that directory.
The API root is /api/v2
. All following routes are relative to this root.
The input can be either
application/json
or application/x-www-form-urlencoded
, with the correct Content-Type
header. For example, as JSON:
{
"username": "[email protected]",
"password": "password"
}
The username could be anything, it's not especially an email. It is what was specified at the user creation time.
If successful, this returns a status 200 with a token in a JSON structure:
{ "token": "ouoiudofiu987987djfjoi..." }
This token should be passed in all subsequent requests as a header Authorization
.
This header should read:
Authorization: Bearer <token>
Any bad credential will return a 401 status. Any good credential will return a new token.
Note: all timestamps are in milliseconds since the UNIX epoch.
Required: the header Authorization
that identifies the user.
This returns the list of reminders for this user as a JSON object.
GET parameters:
start
: as a timestamp, this indicates the start point to return reminders from. Default is now.limit
: as an integer, this indicates how many items should be returned. Default is 20. Specify 0 to return everything to the end.
[{
"id": 1,
"action": "Pick up kids at school",
"created": 1466588359000,
"due": 1466613000000,
"recipients": [{ "id": 1, "forename": "John" }]
}]
Required: the header Authorization
that identifies the user.
This creates a new reminder. Returns the ID for the new reminder as well as the
URL for this reminder in the Location
header.
All properties must be present. There is no default value. For instance (JSON):
{
"recipients": [{ "id": 1 }],
"action": "Pick up kids at school",
"due": 1466613000000
}
- 201 if request succeeded, with
location
header indicating the new resource URL and the body containing the newly inserted recipient:
{
"id": 1,
"recipients": [{ "id": 1, "forename": "John" }],
"action": "Pick up kids at school",
"created": 1466588359000,
"due": 1466613000000
}
- 400 if some properties are missing or invalid.
- 403 if some recipient doesn't have any common group with the logged in user.
Required: the header Authorization
that identifies the user.
This gets the data about a specific reminder.
- 200 if request succeeded, with body:
{
"id": 1,
"recipients": [{ "id": 1, "forename": "John" }],
"action": "Pick up kids at school",
"created": 1466588359000,
"due": 1466613000000
}
- 404 if no reminder with this ID exists or if the logged in user has no common groups with at least 1 recipient.
Required: the header Authorization
that identifies the user.
This returns the list of recipients for this reminder.
- 200 if request succeeded, with body:
[
{
"id": 1,
"forename": "Jane",
"username": "[email protected]",
"phoneNumber": "0123456789" // possibly absent
},
...
]
- 404 if no reminder with this ID exists or if the logged in user has no common groups with at least 1 recipient.
Required: the header Authorization
that identifies the user.
This allows to change a specific reminder.
All properties must be present. For example, if we would like to change only the recipients (JSON):
{
"recipients": [{ "id": 2 }],
"action": "Pick up kids at school",
"due": 1466613000000
}
- 200 with the new data if request succeeded.
- 400 if some properties are missing or invalid.
- 403 if some recipient doesn't have any common group with the logged in user.
- 404 if no reminder with this ID exists or if the logged in user has no common groups with at least 1 recipient.
Required: the header Authorization
that identifies the user.
This allows to partially change a specific reminder. We can't change recipients with this API.
All properties are optional.
{
"action": "Pick up kids at school",
"due": 1466613000000
}
- 200 with the new data if request succeeded.
- 400 if some properties are invalid or no data was passed.
- 404 if no reminder with this ID exists or if the logged in user has no common groups with at least 1 recipient.
Required: the header Authorization
that identifies the user.
This allows to delete a specific reminder.
Only an admin can delete a reminder. Other users should use DELETE /reminders/{id}/recipients/{userId}
instead.
- 204 if request succeeded.
- 403 if the logged in user isn't an admin for one of the groups the recipients are member of.
- 404 if no reminder with this ID exists or the logged in user has no common groups with any recipient.
Required: the header Authorization
that identifies the user.
This allows to remove the logged in user from a reminder.
If the reminder doesn't have any recipient anymore, it's deleted.
- 204 if request succeeded.
- 403 if the user tries to remove another recipient than herself from the reminder.
- 404 if no reminder with this ID exists or if the logged-in user isn't a recipient for this reminder.
This API manages registration for Push endpoints, to send notifications when reminders are (on the edge of being) due.
Required: the header Authorization
that identifies the user.
This registers a new push notification endpoint. Returns the
URL for this endpoint in the Location
header.
All properties must be present. There is no default value. For instance (JSON):
{
"subscription": {
"endpoint": "...",
"keys": {
"p256dh": "<base64>",
"auth": "<base64>"
}
},
"title": "Chrome on Samsung G2"
}
subscription
comes directly from browsers' PushManager API.title
is a free form string. It's intended for the end-user to distinguish between different devices/browsers.
- 201 if request succeeded, with
location
header indicating the new resource URL and a body containing the newly inserted subscription. - 400 if some properties are missing or invalid.
These resources behave like you would expect. Few exceptions:
- GET don't return
auth
. This value should remain secret. - PUT only allows you to modify the
title
. - DELETE removes the subscription.
Push notifications are sent to endpoints when reminders are about to be due.
For Chrome, the application needs to setup its gcm_sender_id
in its manifest.
This id needs to be generated in pair with the server's GCMApiKey on Google's
developer console.
This is the same format as the reminder from the reminders API.
This API manages users.
In all APIs that take an id, using the special string myself
instead of an id
will point to the logged-in user.
Required: the header Authorization
that identifies a user. Only the master
user can create more users.
This creates a new user.
All properties but phoneNumber
must be present. For example:
{
"forename": "Sherlock",
"username": "[email protected]",
"password": "MoriartyShallReturn",
"phoneNumber": "0123456789" // optional
}
The username could be any string as long as it's unique in our database.
Note that the password is stored in database using a modern hash algorithm (Argon2 currently).
- 201 if request succeeded, with
location
header indicating the new resource URL and a body containing the newly inserted user:
{
"id": 1,
"forename": "Sherlock",
"username": "[email protected]"
}
- 400 if some properties are missing or invalid.
Required: the header Authorization
that identifies a user. Only users
belonging in the same group(s) can access information about another user.
This returns information about a user.
- 200 if request succeeded, with body:
{
"id": 1,
"forename": "Sherlock",
"username": "[email protected]",
"phoneNumber": "01234567890" // could be missing
}
- 404 if no user with this ID exists or if the logged-in user is not in a common group.
Required: the header Authorization
that identifies a user. Only a user can see
his own groups.
This returns information about groups a user belongs to.
- 200 if request succeeded, with body:
[
{
"id": 1,
"name": "Holmes",
"location": "https://server.name/api/v2/groups/1",
"isAdmin": "true"
},
{
...
}
]
isAdmin
is true
if this user is an admin of this group.
- 404 if no user with this ID exists or if this user is not the logged-in user.
Required: the header Authorization
that identifies a user. Only a user can see
his own relations.
This returns all users this user has relations with through at least 1 group.
- 200 if request succeeded, with body:
[
{
"id": 2,
"forename": "James",
"username": "[email protected]",
"phoneNumber": "0123456789" // could be absent
},
{
...
}
]
- 404 if no user with this ID exists or if this user is not the logged-in user.
Required: the header Authorization
that identifies a user. A user can only be
modified by himself.
This changes the properties of an existing user.
Note that because this is a dangerous operation we request the user's current password.
All properties except currentPassword are optional. At least one changed property needs to be present.
{
"currentPassword": "MoriartyShallReturn",
"forename": "Sherlock",
"username": "[email protected]",
"phoneNumber": "0123456789",
"newPassword": "HoundOfTheBaskervilles"
}
currentPassword
will be checked against the current password.
- 204 if request succeeded.
- 400 if properties are invalid.
- 403 if
currentPassword
is incorrect. - 404 if no user with this ID exists or if the logged-in user isn't this user.
Required: the header Authorization
that identifies a user. A user can only be
deleted by himself.
This deletes a user.
Because this is a dangerous operation we request the user's password.
{
"currentPassword": "MoriartyShallReturn"
}
- 204 if request succeeded.
- 404 if no user with this ID exists or if the logged-in user isn't this user.
This API manages groups of users.
Required: the header Authorization
that identifies a user.
This creates a new group. The currently logged-in user is an admin for this group and can modify the group, including adding new members.
All properties must be present. There is no default value. For example:
{
"name": "Holmes"
}
- 201 if request succeeded, with
location
header indicating the new resource URL and a body containing the newly inserted group:
{
"id": 1,
"name": "Holmes"
}
- 400 if some properties are missing or invalid.
Required: the header Authorization
that identifies a user. Only a user that
belongs to this group can access its information.
This returns information about a group.
- 200 if request succeeded, with body:
{
"id": 1,
"name": "Holmes"
}
- 404 if no group with this ID exists or if the user doesn't belong to this group.
Required: the header Authorization
that identifies a user. Only a user that
belongs to this group can see its users.
This returns information about users belonging to this group.
- 200 if request succeeded, with body:
[
{
"id": 1,
"forename": "Sherlock",
"username": "[email protected]",
"phoneNumber": "0123456789", // could be missing
"isAdmin": true,
"location": "https://server.name/api/v2/users/1"
},
{
...
}
]
isAdmin
is true if this user is an admin for this group.
- 404 if no user with this ID exists or if the user doesn't belong to this group.
Required: the header Authorization
that identifies a user. A group can only be
modified by one of its admin user.
This will add the user with id userId
to this group.
- 204 if request succeeded.
- 403 if this logged-in user is not an admin for this group.
- 404 if no group with this ID exists or if the logged-in user is not part of this group.
- 409 if this user is already in this group
Required: the header Authorization
that identifies a user. A group can only be
modified by one of its admin user.
This will remove the user with id userId
from this group.
- 204 if request succeeded.
- 403 if this logged-in user is not an admin for this group.
- 404 if no group with this ID exists or if the logged-in user is not part of this group.
Required: the header Authorization
that identifies a user. Only a user that
belongs to this group can see its associated reminders.
This returns all reminders that are associated with users that belong to this group.
GET parameters:
start
: as a timestamp, this indicates the start point to return reminders from. Default is now.limit
: as an integer, this indicates how many items should be returned. Default is 20. Specify 0 to return everything to the end.
[{
"id": 1,
"recipients": [{ "id": 1, "forename": "Jane" }],
"action": "Pick up kids at school",
"created": 1466588359000,
"due": 1466613000000
}]
Required: the header Authorization
that identifies a user. A group can only be
modified by one of its admin user.
This changes the properties of a group.
All properties must be present. For example:
{
"name": "The_Avengers"
}
- 204 if request succeeded.
- 400 if some properties are missing or invalid.
- 403 if this logged-in user is not an admin for this group.
- 404 if no group with this ID exists or if the logged-in user is not part of this group.
Required: the header Authorization
that identifies a user. A group can only be
deleted by an admin user.
This deletes a group.
- 204 if request succeeded.
- 404 if no group with this ID exists or the logged-in user is not part of this group.