AirBnBeyond is an online marketplace that connects travelers with unique accommodations and experiences. Inspired by AirBnB, whether you're seeking a cozy cottage or an adventurous city stay, AirBnBeyond offers a diverse range of options to make your travels memorable.
Check out AirBnBeyond
Clone this repository:
https://github.com/CodeJellee/API-project.git
Install denpendencies into the Backed and the Frontend by making a terminal for each one and then run the following:
npm install
Create a .env file using the .envexample provided
Set up your database with information from your .env and then run the following to create your database, migrate, and seed:
npx dotenv sequelize db:create
npx dotenv sequelize db:migrate
npx dotenv sequelize db:seed:all
Start the app for both backend and frontend using:
npm start
Now you can use the Demo User or Create an account
Logged-in Users can
Logged-in Users can
Logged in Users can
Request | Purpose | Return Value |
---|---|---|
GET/api/auth/ | This fetch is sent upon initial app load an on subsequent refreshes. It returns an object representing the current user, if user is logged in. | 283 |
GET/api/login/ | This fetch attempts to login a user with the provided credientials. It returns an object representing the current user, if validation succeeds. | 283 |
All endpoints that require a current user to be logged in.
Error Response: Require authentication
{
"message": "Authentication required"
}
All endpoints that require authentication and the current user does not have the correct role(s) or permission(s).
Error Response: Require proper authorization
{
"message": "Forbidden"
}
Returns the information about the current user that is logged in.
Require Authentication: true
Request
Successful Response when there is a logged in user
{
"user": {
"id": 1,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@gmail.com",
"username": "JohnSmith"
}
}
Successful Response when there is no logged in user
{
"user": null
}
Logs in a current user with valid credentials and returns the current user's information.
Require Authentication: false
Request
{
"credential": "john.smith@gmail.com",
"password": "secret password"
}
Successful Response
{
"user": {
"id": 1,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@gmail.com",
"username": "JohnSmith"
}
}
Error Response: Invalid credentials
{
"message": "Invalid credentials"
}
Error response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"credential": "Email or username is required",
"password": "Password is required"
}
}
Creates a new user, logs them in as the current user, and returns the current user's information.
Require Authentication: false
Request
{
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@gmail.com",
"username": "JohnSmith",
"password": "secret password"
}
Successful Response
{
"user": {
"id": 1,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@gmail.com",
"username": "JohnSmith"
}
}
Error response: User already exists with the specified email
{
"message": "User already exists",
"errors": {
"email": "User with that email already exists"
}
}
Error response: User already exists with the specified username
{
"message": "User already exists",
"errors": {
"username": "User with that username already exists"
}
}
Error response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"email": "Invalid email",
"username": "Username is required",
"firstName": "First Name is required",
"lastName": "Last Name is required"
}
}
Returns all the spots.
Require Authentication: false
Request
Successful Response
{
"Spots": [
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36",
"avgRating": 4.5,
"previewImage": "image url"
}
]
}
Returns all the spots owned (created) by the current user.
Require Authentication: true
Request
Successful Response
{
"Spots": [
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36",
"avgRating": 4.5,
"previewImage": "image url"
}
]
}
Returns the details of a spot specified by its id.
Require Authentication: false
Request
Successful Response
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36" ,
"numReviews": 5,
"avgStarRating": 4.5,
"SpotImages": [
{
"id": 1,
"url": "image url",
"preview": true
},
{
"id": 2,
"url": "image url",
"preview": false
}
],
"Owner": {
"id": 1,
"firstName": "John",
"lastName": "Smith"
}
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Creates and returns a new spot.
Require Authentication: true
Request
{
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123
}
Successful Response
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36"
}
Error Response: Body validation error
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"address": "Street address is required",
"city": "City is required",
"state": "State is required",
"country": "Country is required",
"lat": "Latitude is not valid",
"lng": "Longitude is not valid",
"name": "Name must be less than 50 characters",
"description": "Description is required",
"price": "Price per day is required"
}
}
Create and return a new image for a spot specified by id.
Require Authentication: true
Require proper authorization: Spot must belong to the current user
Request
{
"url": "image url",
"preview": true
}
Successful Response
{
"id": 1,
"url": "image url",
"preview": true
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Updates and returns an existing spot.
Require Authentication: true
Require proper authorization: Spot must belong to the current user
Request
{
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123
}
Successful Response
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-20 10:06:40"
}
Error Response: Body validation error
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"address": "Street address is required",
"city": "City is required",
"state": "State is required",
"country": "Country is required",
"lat": "Latitude is not valid",
"lng": "Longitude is not valid",
"name": "Name must be less than 50 characters",
"description": "Description is required",
"price": "Price per day is required"
}
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Deletes an existing spot.
Require Authentication: true
Require proper authorization: Spot must belong to the current user
Request
Successful Response
{
"message": "Successfully deleted"
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Returns all the reviews written by the current user.
Require Authentication: true
Request
Successful Response
{
"Reviews": [
{
"id": 1,
"userId": 1,
"spotId": 1,
"review": "This was an awesome spot!",
"stars": 5,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36" ,
"User": {
"id": 1,
"firstName": "John",
"lastName": "Smith"
},
"Spot": {
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"price": 123,
"previewImage": "image url"
},
"ReviewImages": [
{
"id": 1,
"url": "image url"
}
]
}
]
}
Returns all the reviews that belong to a spot specified by id.
Require Authentication: false
Request
Successful Response
{
"Reviews": [
{
"id": 1,
"userId": 1,
"spotId": 1,
"review": "This was an awesome spot!",
"stars": 5,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36" ,
"User": {
"id": 1,
"firstName": "John",
"lastName": "Smith"
},
"ReviewImages": [
{
"id": 1,
"url": "image url"
}
],
}
]
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Create and return a new review for a spot specified by id.
Require Authentication: true
Request
{
"review": "This was an awesome spot!",
"stars": 5,
}
Successful Response
{
"id": 1,
"userId": 1,
"spotId": 1,
"review": "This was an awesome spot!",
"stars": 5,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36"
}
Error Response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"review": "Review text is required",
"stars": "Stars must be an integer from 1 to 5",
}
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Error response: Review from the current user already exists for the Spot
{
"message": "User already has a review for this spot"
}
Create and return a new image for a review specified by id.
Require Authentication: true
Require proper authorization: Review must belong to the current user
Request
{
"url": "image url"
}
Successful Response
{
"id": 1,
"url": "image url"
}
Error response: Couldn't find a Review with the specified id
{
"message": "Review couldn't be found"
}
Error response: Cannot add any more images because there is a maximum of 10 images per resource
{
"message": "Maximum number of images for this resource was reached"
}
Update and return an existing review.
Require Authentication: true
Require proper authorization: Review must belong to the current user
Request
{
"review": "This was an awesome spot!",
"stars": 5,
}
Successful Response
{
"id": 1,
"userId": 1,
"spotId": 1,
"review": "This was an awesome spot!",
"stars": 5,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-20 10:06:40"
}
Error Response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"review": "Review text is required",
"stars": "Stars must be an integer from 1 to 5",
}
}
Error response: Couldn't find a Review with the specified id
{
"message": "Review couldn't be found"
}
Delete an existing review.
Require Authentication: true
Require proper authorization: Review must belong to the current user
Request
Successful Response
{
"message": "Successfully deleted"
}
Error response: Couldn't find a Review with the specified id
{
"message": "Review couldn't be found"
}
Return all the bookings that the current user has made.
Require Authentication: true
Request
Successful Response
{
"Bookings": [
{
"id": 1,
"spotId": 1,
"Spot": {
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"price": 123,
"previewImage": "image url"
},
"userId": 2,
"startDate": "2021-11-19",
"endDate": "2021-11-20",
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36"
}
]
}
Return all the bookings for a spot specified by id.
Require Authentication: true
Request
Successful Response: If you ARE NOT the owner of the spot.
{
"Bookings": [
{
"spotId": 1,
"startDate": "2021-11-19",
"endDate": "2021-11-20"
}
]
}
Successful Response: If you ARE the owner of the spot.
{
"Bookings": [
{
"User": {
"id": 2,
"firstName": "John",
"lastName": "Smith"
},
"id": 1,
"spotId": 1,
"userId": 2,
"startDate": "2021-11-19",
"endDate": "2021-11-20",
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36"
}
]
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Create and return a new booking from a spot specified by id.
Require Authentication: true
Require proper authorization: Spot must NOT belong to the current user
Request
{
"startDate": "2021-11-19",
"endDate": "2021-11-20"
}
Successful Response
{
"id": 1,
"spotId": 1,
"userId": 2,
"startDate": "2021-11-19",
"endDate": "2021-11-20",
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36"
}
Error response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"endDate": "endDate cannot be on or before startDate"
}
}
Error response: Couldn't find a Spot with the specified id
{
"message": "Spot couldn't be found"
}
Error response: Booking conflict
{
"message": "Sorry, this spot is already booked for the specified dates",
"errors": {
"startDate": "Start date conflicts with an existing booking",
"endDate": "End date conflicts with an existing booking"
}
}
Update and return an existing booking.
Require Authentication: true
Require proper authorization: Booking must belong to the current user
Request
{
"startDate": "2021-11-19",
"endDate": "2021-11-20"
}
Successful Response
{
"id": 1,
"spotId": 1,
"userId": 2,
"startDate": "2021-11-19",
"endDate": "2021-11-20",
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-20 10:06:40"
}
Error response: Body validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"endDate": "endDate cannot come before startDate"
}
}
Error response: Couldn't find a Booking with the specified id
{
"message": "Booking couldn't be found"
}
Error response: Can't edit a booking that's past the end date
{
"message": "Past bookings can't be modified"
}
Error response: Booking conflict
{
"message": "Sorry, this spot is already booked for the specified dates",
"errors": {
"startDate": "Start date conflicts with an existing booking",
"endDate": "End date conflicts with an existing booking"
}
}
Delete an existing booking.
Require Authentication: true
Require proper authorization: Booking must belong to the current user or the Spot must belong to the current user
Request
Successful Response
{
"message": "Successfully deleted"
}
Error response: Couldn't find a Booking with the specified id
{
"message": "Booking couldn't be found"
}
Error response: Bookings that have been started can't be deleted
{
"message": "Bookings that have been started can't be deleted"
}
Delete an existing image for a Spot.
Require Authentication: true
Require proper authorization: Spot must belong to the current user
Request
Successful Response
{
"message": "Successfully deleted"
}
Error response: Couldn't find a Spot Image with the specified id
{
"message": "Spot Image couldn't be found"
}
Delete an existing image for a Review.
Require Authentication: true
Require proper authorization: Review must belong to the current user
Request
Successful Response
{
"message": "Successfully deleted"
}
Error response: Couldn't find a Review Image with the specified id
{
"message": "Review Image couldn't be found"
}
Return spots filtered by query parameters.
Require Authentication: false
Request
Successful Response
{
"Spots": [
{
"id": 1,
"ownerId": 1,
"address": "123 Disney Lane",
"city": "San Francisco",
"state": "California",
"country": "United States of America",
"lat": 37.7645358,
"lng": -122.4730327,
"name": "App Academy",
"description": "Place where web developers are created",
"price": 123,
"createdAt": "2021-11-19 20:39:36",
"updatedAt": "2021-11-19 20:39:36",
"avgRating": 4.5,
"previewImage": "image url"
}
],
"page": 2,
"size": 25
}
Error Response: Query parameter validation errors
{
"message": "Bad Request", // (or "Validation error" if generated by Sequelize),
"errors": {
"page": "Page must be greater than or equal to 1",
"size": "Size must be greater than or equal to 1",
"maxLat": "Maximum latitude is invalid",
"minLat": "Minimum latitude is invalid",
"minLng": "Maximum longitude is invalid",
"maxLng": "Minimum longitude is invalid",
"minPrice": "Minimum price must be greater than or equal to 0",
"maxPrice": "Maximum price must be greater than or equal to 0"
}
}