A Postgres API server using Node, Express, bcrypt and token-based authentication using JWTs.
The API is deployed on the Heroku free tier. Please allow 5-10 seconds for Heroku to "wake up" the connection when using an endpoint for the first time that day.
The url to the deployed server is: https://sleeptrackerbw.herokuapp.com/
Since axios returns data in an object that also has a data
property, you should plan to access the data from the API requests by referencing res.data.data
. If you would prefer to rename the data
property of the object returned by axios, then using interceptors is probably the most expedient method to rename it from data
to body
(to mimic the shape returned by the fetch API)
Name | Type | Description |
---|---|---|
message | String |
A status message |
validation | Array |
An array of validation errors |
data | Object |
An object containing any data returned by the resource |
HTTP 1.1/*
{
"message": "",
"validation": [],
"data": {}
}
export const axiosWithAuth = () => {
const instance = axios.create({
baseURL: "http://localhost:5000/api",
headers: {
authorization: localStorage.getItem("token"),
},
});
// Reshape the response to avoid res.data.data
// Use the res.body shape, similar to the fetch API
instance.interceptors.response.use((response) => {
const body = { ...response.data };
delete response.data; // remove the data property
return { ...response, body };
});
return instance
};
Logs In a User
POST /api/login
Name | Type | Description |
---|---|---|
username | String |
The username for the new user |
password | String |
The password for the new user |
json
- Request Example:
{
"username": "david1234",
"password": "1234"
}
Name | Type | Description |
---|---|---|
user | Object |
The user object and the token |
HTTP/1.1 200: Success
{
"message": "Welcome, david1234!",
"validation": [],
"data": {
"user": {
"id": 3,
"username": "david1234",
"role": 1,
"first_name": "David",
"last_name": "White",
"email": null
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey..."
}
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
{
"message": "Invalid Username",
"validation": ["There was a problem retrieving the username"],
"data": {}
}
Registers a New User
POST /api/register
Name | Type | Description |
---|---|---|
username | String |
The username for the new user |
password | String |
The password for the new user |
role | Integer |
The role for the new user |
first_name | String |
optional The first name for the new user |
last_name | String |
optional The last name for the new user |
String |
optional The email for the new user |
json
- Request Example:
{
"username": "david1234",
"password": "1234",
"role": 1,
"first_name": "David",
"last_name": "White"
}
Name | Type | Description |
---|---|---|
user | Object |
The object containing the new user data |
HTTP/1.1 201: Created
{
"message": "Registered david1234 successfully",
"validation": [],
"data": {
"user": {
"id": 3,
"username": "david1234",
"role": 1,
"first_name": "David",
"last_name": "White",
"email": null
}
}
HTTP/1.1 400: Bad Request
{
"message": "Invalid Username",
"validation": [
"Username is invalid"
],
"data": {}
}
Delete a mood record by id
DELETE /api/mood/:id
Name | Type | Description |
---|---|---|
message | Object |
The standard shape with a success message is sent back |
HTTP/1.1 204: No Content
{
"message": "The mood entry with id 1 has been successfully deleted",
"validation": [],
"data": {}
}
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
{
"message": "There was a problem completing the required operation",
"validation": [],
"data": {}
}
Delete a sleep record by id
DELETE /api/sleep/:id
Name | Type | Description |
---|---|---|
message | Object |
The standard shape with a success message is sent back |
HTTP/1.1 204: No Content
{
"message": "The sleep entry with id 1 has been successfully deleted",
"validation": [],
"data": {}
}
HTTP/1.1 401: Unauthorized
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
HTTP/1.1 500: Server Error
{
"message": "There was a problem completing the required operation",
"validation": [],
"data": {}
}
Get All Sleep, with optional query string support
GET /api/sleep
Using start
and end
query params to filter the data by date:
GET /api/sleep?start='4/01/2020'&end='4/17/2020'
Use the page
and limit
query params to enable pagination:
GET /api/sleep?limit=10&page=2
Combine both date and pagination query string params if desired
GET /api/sleep?start='4/01/2020'&end='4/17/2020'&limit=10&page=2
Name | Type | Description |
---|---|---|
sleep | Array |
An array of objects with the sleep information |
HTTP/1.1 200: OK
{
"message": "Success",
"validation": [],
"data": [
{
"id": 1,
"user_id": 3,
"sleep_start": "1585782000000",
"sleep_end": "1585832400000",
"start_formatted": "04/01/2020 11:00 PM",
"end_formatted": "04/02/2020 1:00 PM",
"sleep_goal": 11,
"sleep_hours": 14,
"mood_waking": 4,
"mood_day": 1,
"mood_bedtime": 4
},
{
"id": 2,
"user_id": 3,
"sleep_start": "1585868400000",
"sleep_end": "1585915200000",
"start_formatted": "04/02/2020 11:00 PM",
"end_formatted": "04/03/2020 12:00 PM",
"sleep_goal": 8,
"sleep_hours": 13,
"mood_waking": 3,
"mood_day": 1,
"mood_bedtime": 1
},
{
"id": 3,
"user_id": 3,
"sleep_start": "1585947600000",
"sleep_end": "1585969200000",
"start_formatted": "04/03/2020 9:00 PM",
"end_formatted": "04/04/2020 3:00 AM",
"sleep_goal": 10,
"sleep_hours": 6,
"mood_waking": 3,
"mood_day": 1,
"mood_bedtime": 4
}
]
}
HTTP/1.1 401: Unauthorized
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
Get Sleep By Id
GET /api/sleep/:id
Name | Type | Description |
---|---|---|
sleep | Array |
An array with an object with the sleep information |
HTTP/1.1 200: OK
{
"message": "Success",
"validation": [],
"data": [
{
"id": 1,
"user_id": 3,
"sleep_start": "1585782000000",
"sleep_end": "1585832400000",
"start_formatted": "04/01/2020 11:00 PM",
"end_formatted": "04/02/2020 1:00 PM",
"sleep_goal": 11,
"sleep_hours": 14,
"mood_waking": 4,
"mood_day": 1,
"mood_bedtime": 4
}
]
}
HTTP/1.1 401: Unauthorized
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
Add a sleep record
POST /api/sleep
Name | Type | Description |
---|---|---|
sleep_start | Integer |
The start time for the sleep entry |
sleep_end | Integer |
The end time for the sleep entry |
user_id | Integer |
The user id of the person who slept |
mood_waking | Integer |
The user's mood score on waking (1-4) |
mood_day | Integer |
The user's mood score during the day (1-4) |
mood_bedtime | Integer |
The user's mood score at bedtime (1-4) |
json
- Request Example:
{
"sleep_start": 1588039200000,
"sleep_end": 1588068000000,
"sleep_goal": 6,
"user_id": 3,
"mood_waking": 4,
"mood_day": 3,
"mood_bedtime": 2
}
Name | Type | Description |
---|---|---|
sleep | Array |
An array with the object with the information |
HTTP/1.1 201: Created
{
"message": "The sleep entry has been successfully added",
"validation": [],
"data": [
{
"id": 1,
"sleep_start": 1588039200000,
"sleep_end": 1588068000000,
"sleep_goal": 6,
"user_id": 3,
"mood_waking": 4,
"mood_day": 3,
"mood_bedtime": 2
}
]
}
HTTP/1.1 401: Unauthorized
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
Update a sleep record by id
PUT /api/sleep/:id
Name | Type | Description |
---|---|---|
property | Object |
Any property on the sleep record |
json
- Request Example:
{
"sleep_end": 1588068000000
}
Name | Type | Description |
---|---|---|
sleep | Array |
An array with the object with the updated information |
HTTP/1.1 200: OK
{
"message": "The sleep entry has been successfully updated",
"validation": [],
"data": [
{
"id": 1,
"sleep_start": 1588039200000,
"sleep_end": 1588068000000,
"sleep_goal": 6,
"user_id": 3,
"mood_waking": 4,
"mood_day": 3,
"mood_bedtime": 2
}
]
}
HTTP/1.1 401: Unauthorized
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
HTTP/1.1 500: Server Error
{
"message": "There was a problem completing the required operation",
"validation": [],
"data": {}
}
Get All Users
GET /api/users
Name | Type | Description |
---|---|---|
users | Array |
An array of user objects |
HTTP/1.1 200: OK
{
"message": "Success",
"validation": [],
"data": [
{
"id": 1,
"username": "test1",
"role": 1,
"first_name": "Test",
"last_name": "User 1",
"email": "test@testing.com"
},
{
"id": 2,
"username": "test2",
"role": 1,
"first_name": "Test",
"last_name": "User 2",
"email": "test@testing.com"
},
{
"id": 3,
"username": "test3",
"role": 1,
"first_name": "Test",
"last_name": "User 3",
"email": "test@testing.com"
}
]
}
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
Get a User by Id
GET /api/users/:id
Name | Type | Description |
---|---|---|
user | Object |
An object with the user information |
HTTP/1.1 200: OK
{
"message": "Success",
"validation": [],
"data": {
"id": 1,
"username": "test1",
"role": 1,
"first_name": "Test",
"last_name": "User 1",
"email": "test@testing.com"
}
}
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
Update a User by Id
PUT /api/users/:id
Name | Type | Description |
---|---|---|
property | Object |
Any property on the user record |
json
- Request Example:
{
"role": 2,
"first_name": "Updated Test"
}
Name | Type | Description |
---|---|---|
user | Object |
An object with the updated information |
HTTP/1.1 200: OK
{
"message": "Success",
"validation": [],
"data": {
"id": 1,
"username": "test1",
"role": 2,
"first_name": "Updated Test",
"last_name": "User 1",
"email": "test@testing.com"
}
}
{
"message": "Invalid Credentials",
"validation": [],
"data": {}
}
{
"message": "There was a problem completing the required operation",
"validation": [],
"data": {}
}