├── .gitignore ├── LICENSE ├── README.md ├── api ├── getCalendar.js ├── getListing.js ├── getListings.js ├── getMessageThread.js ├── getMessageThreads.js ├── getPayouts.js ├── getReservation.js ├── getUser.js ├── login.js ├── postCalendar.js └── sendMessage.js ├── bnbhostapi.js ├── config.js ├── examples ├── getCalendar.js ├── getListings.js ├── getMessages.js ├── getPayouts.js ├── getReservation.js ├── getUser.js ├── login.js ├── postCalendar.js └── sendMessage.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | setup.sh 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 David Plappert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bnbhostapi 2 | ====== 3 | 4 | I, David Plappert, am an Airbnb Superhost. I, also, want to be able to build tools to support my business, the way I want. Currently, I pay about $40 per month for tools that only do some of what I want. [SmartBnb](http://smartbnb.io), [Properly](http://getproperly.com), [QuickBooks](https://quickbooks.intuit.com/), and others are a good start. However, I want more control, customization and automation. 5 | 6 | ### This wrapper exposes API end points that allow you to: 7 | - login to Airbnb and get an oauth token (this has to be frist before you do anything else) 8 | - Get listings 9 | - Get listing details 10 | - Get messages 11 | - Get message details 12 | - Send messages 13 | - Get calendar for a listing 14 | - Update calendar for a listing (change prices, availbility, notes) 15 | - get Payouts (used to get a list of reservations, past and future - also gives you exact $ for accounting) 16 | - get reservation details 17 | - get user details (info about your guests) 18 | 19 | ### To set this API up, follow these steps: 20 | I assume you have node installed (nvm maybe?) and that you have a listing on AirBnb. 21 | 1) `npm install bnbhostapi` (or `git clone git@github.com:davidplappert/bnbhostapi.git && npm install`) 22 | 2) `export bnbhostapi_username='xxxxxxx'` (replace with your email) 23 | 3) `export bnbhostapi_password='xxxxxxx'` (replace with your password) 24 | 4) `node examples/login.js` (this generates a oauth token we need for the rest of the api calls) 25 | 5) `export bnbhostapi_oauthtoken = xxxxxx` (output from the above script) 26 | 6) `node examples/getPayouts.js` (to make sure your setup is correct). 27 | 28 | ### This following sippet will return all your payout info along with all the reservation info. 29 | 30 | ``` 31 | var bnbhostapi = require('bnbhostapi'); 32 | bnbhostapi.getPayouts(true). 33 | each(function(payout){ 34 | bnbhostapi.getReservation(payout['reservation']['confirmation_code']) 35 | .then(function(reservation){ 36 | console.log(reservation); 37 | }); 38 | }); 39 | ``` 40 | 41 | ### Forward looking features: 42 | - leave reviews 43 | - charge for extra services 44 | - stats and more details for reporting 45 | 46 | ## Credits: 47 | - [Charles Proxy](https://www.charlesproxy.com/) 48 | - [Postman](https://www.getpostman.com/) 49 | - [airbnbapi.com](http://airbnbapi.com/) 50 | - [airapi](https://github.com/phamtrisi/airapi) 51 | -------------------------------------------------------------------------------- /api/getCalendar.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getCalendar(listing_id,start_date=null,end_date=null){ 6 | //figure out date if none is put in 7 | var date = new Date(); 8 | date.setDate(0); 9 | if (start_date == null){ 10 | start_date = date.getFullYear() + '-' + ( '0' + parseInt(date.getMonth()+1)).slice(-2) + '-' + ( '0' + date.getDate()).slice(-2); 11 | } 12 | if (end_date == null){ 13 | date.setMonth(date.getMonth() + 3); 14 | date.setDate(1); 15 | var end_date = date.getFullYear() + '-' + ( '0' + parseInt(date.getMonth()+1)).slice(-2) + '-' + ( '0' + date.getDate()).slice(-2); 16 | } 17 | var options = { 18 | method: 'GET', 19 | url: 'https://api.airbnb.com/v2/calendars/' + listing_id + '/' + start_date + '/' + end_date, 20 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 21 | qs: { 22 | '_format':'host_calendar_detailed', 23 | }, 24 | gzip: true, 25 | }; 26 | return new promise(function(resolve, reject) { 27 | request(options, function (error, response, body) { 28 | if (error){ 29 | reject(error); 30 | }else{ 31 | body = JSON.parse(body); 32 | if (body['error_code']){ 33 | reject(body); 34 | }else{ 35 | resolve(body['calendar']); 36 | } 37 | } 38 | }); 39 | }); 40 | } 41 | 42 | module.exports = getCalendar; 43 | -------------------------------------------------------------------------------- /api/getListing.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getListings(listing_id){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/listings/' + listing_id, 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | '_format':'v1_legacy_long_manage_listing', 12 | }, 13 | gzip: true, 14 | }; 15 | return new promise(function(resolve, reject) { 16 | request(options, function (error, response, body) { 17 | if (error){ 18 | reject(error); 19 | }else{ 20 | body = JSON.parse(body); 21 | if (body['error_code']){ 22 | reject(body); 23 | }else{ 24 | resolve(body['listing']); 25 | } 26 | } 27 | }); 28 | }); 29 | } 30 | 31 | module.exports = getListings; 32 | -------------------------------------------------------------------------------- /api/getListings.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getListings(limit=50,offset=0){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/listings/', 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | '_limit':limit, 12 | '_offset':offset, 13 | '_format':'for_manage_listing_app_pending', 14 | 'has_availability':false, 15 | 'user_id': config['bnbhostapi']['user_id'] 16 | }, 17 | gzip: true, 18 | }; 19 | return new promise(function(resolve, reject) { 20 | request(options, function (error, response, body) { 21 | if (error){ 22 | reject(error); 23 | }else{ 24 | body = JSON.parse(body); 25 | if (body['error_code']){ 26 | reject(body); 27 | }else{ 28 | resolve(body['listings']); 29 | } 30 | } 31 | }); 32 | }); 33 | } 34 | 35 | module.exports = getListings; 36 | -------------------------------------------------------------------------------- /api/getMessageThread.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getMessageThread(thread_id,limit=50,offset=0){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/threads/' + thread_id, 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | _limit:limit, 12 | _ofset:offset, 13 | selected_inbox_type: 'host', 14 | _format: 'for_messaging_sync_with_posts' 15 | }, 16 | gzip: true, 17 | }; 18 | return new promise(function(resolve, reject) { 19 | request(options, function (error, response, body) { 20 | if (error){ 21 | reject(error); 22 | }else{ 23 | body = JSON.parse(body); 24 | if (body['error_code']){ 25 | reject(body); 26 | }else{ 27 | resolve(body['thread']); 28 | } 29 | } 30 | }); 31 | }); 32 | } 33 | 34 | module.exports = getMessageThread; 35 | -------------------------------------------------------------------------------- /api/getMessageThreads.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getMessageThreads(limit=50,offset=0,archived=false){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/threads/', 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | _limit:limit, 12 | _offset:offset, 13 | selected_inbox_type:'host', 14 | _format:'for_messaging_sync', 15 | //include_support_messaging_threads:false 16 | }, 17 | gzip: true, 18 | }; 19 | if (archived){ 20 | options['qs']['role'] = "hidden"; 21 | } 22 | return new promise(function(resolve, reject) { 23 | request(options, function (error, response, body) { 24 | if (error){ 25 | reject(error); 26 | }else{ 27 | body = JSON.parse(body); 28 | if (body['error_code']){ 29 | reject(body); 30 | }else{ 31 | resolve(body['threads']); 32 | } 33 | } 34 | }); 35 | }); 36 | } 37 | 38 | module.exports = getMessageThreads; 39 | -------------------------------------------------------------------------------- /api/getPayouts.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | /** 6 | Sending pending true to get future payouts, false to get past payouts 7 | 8 | limit max is 20 9 | **/ 10 | 11 | function getPayouts(pending=false,limit=20,offset=0){ 12 | var options = { 13 | method: 'GET', 14 | url: 'https://api.airbnb.com/v2/payouts/', 15 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 16 | qs: { 17 | '_limit':limit, 18 | '_offset':offset, 19 | '_format':'for_mobile_transaction_history', 20 | 'pending':pending, 21 | }, 22 | gzip: true, 23 | }; 24 | if (!pending){ 25 | //confirmation code: ['line_items'][0]['reservation']['confirmation_code'] 26 | options['qs']['_format'] = 'for_mobile_transaction_history_payout'; 27 | }else{ 28 | //confirmation code: ['reservation']['confirmation_code'] 29 | } 30 | return new promise(function(resolve, reject) { 31 | request(options, function (error, response, body) { 32 | if (error){ 33 | reject(error); 34 | }else{ 35 | body = JSON.parse(body); 36 | if (body['error_code']){ 37 | reject(body); 38 | }else{ 39 | resolve(body['payouts']); 40 | } 41 | } 42 | }); 43 | }); 44 | } 45 | 46 | module.exports = getPayouts; 47 | -------------------------------------------------------------------------------- /api/getReservation.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getReservation(confirmation_code){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/reservations/' + confirmation_code, 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | '_format':'for_mobile_host', 12 | }, 13 | gzip: true, 14 | }; 15 | return new Promise(function(resolve, reject) { 16 | request(options, function (error, response, body) { 17 | if (error){ 18 | reject(error); 19 | }else{ 20 | body = JSON.parse(body); 21 | if (body['error_code']){ 22 | reject(body); 23 | }else{ 24 | resolve(body['reservation']); 25 | } 26 | } 27 | }); 28 | }); 29 | } 30 | 31 | module.exports = getReservation; 32 | -------------------------------------------------------------------------------- /api/getUser.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function getUser(user_id){ 6 | var options = { 7 | method: 'GET', 8 | url: 'https://api.airbnb.com/v2/users/' + user_id, 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | qs: { 11 | '_format':'with_content_framework_articles' 12 | }, 13 | gzip: true, 14 | }; 15 | return new promise(function(resolve, reject) { 16 | request(options, function (error, response, body) { 17 | if (error){ 18 | reject(error); 19 | }else{ 20 | body = JSON.parse(body); 21 | if (body['error_code']){ 22 | reject(body); 23 | }else{ 24 | resolve(body['user']); 25 | } 26 | } 27 | }); 28 | }); 29 | } 30 | 31 | module.exports = getUser; 32 | -------------------------------------------------------------------------------- /api/login.js: -------------------------------------------------------------------------------- 1 | /*** 2 | 3 | Be very careful when using this 4 | Airbnb will only give you so many tokens per hour 5 | once you get your token, set it in your env like this: 6 | 7 | export bnbhostapi_oauthtoken='XXXXXXXXXXXXXX' 8 | 9 | this token should last for a while, say 3 months 10 | 11 | **/ 12 | 13 | var request = require("request"); 14 | var promise = require('bluebird'); 15 | var config = require('../config'); 16 | 17 | function login(){ 18 | var options = { 19 | method: 'POST', 20 | url: 'https://api.airbnb.com/v1/authorize', 21 | headers: JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 22 | gzip: true, 23 | form: { 24 | grant_type: 'password', 25 | password: config['bnbhostapi']['password'], 26 | username: config['bnbhostapi']['username'], 27 | } 28 | }; 29 | options['headers']['Content-Type'] = 'application/x-www-form-urlencoded'; 30 | return new promise(function(resolve, reject) { 31 | request(options, function (error, response, body) { 32 | if (error){ 33 | reject(error); 34 | }else{ 35 | //body = JSON.parse(body); 36 | resolve(body) 37 | //['access_token']; 38 | } 39 | }); 40 | }); 41 | } 42 | 43 | module.exports = login; 44 | -------------------------------------------------------------------------------- /api/postCalendar.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | /* 6 | 7 | single date: date = '2018-12-31' 8 | date range: date = '2018-12-30:2018-12-31' 9 | 10 | */ 11 | 12 | function postCalendar(listing_id, date, daily_price=null, smart_pricing_override=null, available=null, notes=null){ 13 | var operations = []; 14 | if (smart_pricing != null){ 15 | operations.push({ 16 | "dates":[date], 17 | "demand_based_pricing_overridden":smart_pricing_override 18 | }); 19 | if (!smart_pricing){ 20 | if (daily_price != null){ 21 | operations.push({ 22 | "dates":[date], 23 | "daily_price":daily_price 24 | }); 25 | } 26 | } 27 | } 28 | if (available != null){ 29 | var av; 30 | if (available){ 31 | av = 'available' 32 | }else{ 33 | av = 'unavailable_persistent' 34 | } 35 | operations.push({ 36 | "dates":[date], 37 | "availability":av 38 | }); 39 | } 40 | if (notes != null){ 41 | operations.push({ 42 | "dates":[date], 43 | "notes":notes 44 | }); 45 | } 46 | var options = { 47 | method: 'POST', 48 | url: 'https://api.airbnb.com/v2/calendar_operations/', 49 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 50 | qs: { 51 | '_allow_dates_overlap':true, 52 | }, 53 | body: JSON.stringify({ 54 | "operations":operations, 55 | "listing_id":listing_id, 56 | "method":"UPDATE" 57 | }), 58 | gzip: true, 59 | }; 60 | return new promise(function(resolve, reject) { 61 | request(options, function (error, response, body) { 62 | if (error){ 63 | reject(error); 64 | }else{ 65 | body = JSON.parse(body); 66 | if (body['error_code']){ 67 | reject(body); 68 | }else{ 69 | resolve(body); 70 | } 71 | } 72 | }); 73 | }); 74 | } 75 | 76 | module.exports = postCalendar; 77 | -------------------------------------------------------------------------------- /api/sendMessage.js: -------------------------------------------------------------------------------- 1 | var request = require("request"); 2 | var promise = require('bluebird'); 3 | var config = require('../config'); 4 | 5 | function sendMessage(thread_id, message){ 6 | var options = { 7 | method: 'POST', 8 | url: 'https://api.airbnb.com/v2/messages', 9 | headers:JSON.parse(JSON.stringify(config['bnbhostapi']['headers'])), 10 | body: JSON.stringify({ 11 | "message":message, 12 | "thread_id":thread_id 13 | }), 14 | gzip: true, 15 | }; 16 | console.log(options); 17 | return new promise(function(resolve, reject) { 18 | request(options, function (error, response, body) { 19 | if (error){ 20 | reject(error); 21 | }else{ 22 | body = JSON.parse(body); 23 | resolve(body); 24 | } 25 | }); 26 | }); 27 | } 28 | 29 | module.exports = sendMessage; 30 | -------------------------------------------------------------------------------- /bnbhostapi.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | login: require('./api/login'), 4 | getListings: require('./api/getListings'), 5 | getListing: require('./api/getListing'), 6 | getMessageThreads: require('./api/getMessageThreads'), 7 | getMessageThread: require('./api/getMessageThread'), 8 | sendMessage: require('./api/sendMessage'), 9 | getReservation: require('./api/getReservation'), 10 | getPayouts: require('./api/getPayouts'), 11 | getUser: require('./api/getUser'), 12 | getCalendar: require('./api/getCalendar'), 13 | postCalendar: require('./api/postCalendar') 14 | }; 15 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = { 2 | username: process.env.bnbhostapi_username, 3 | password: process.env.bnbhostapi_password, 4 | user_id: process.env.bnbhostapi_userid, 5 | headers: { 6 | 'cache-control': 'no-cache', 7 | 'user-agent': 'Airbnb/17.50 iPad/11.2.1 Type/Tablet', 8 | 'content-type': 'application/json', 9 | 'accept': 'application/json', 10 | 'accept-encoding': 'br, gzip, deflate', 11 | 'accept-language': 'en-us', 12 | 'x-airbnb-oauth-token': process.env.bnbhostapi_oauthtoken, 13 | 'x-airbnb-api-key': '915pw2pnf4h1aiguhph5gc5b2', 14 | 'x-airbnb-locale': 'en', 15 | 'x-airbnb-currency': 'USD', 16 | } 17 | } 18 | 19 | module.exports = { 20 | bnbhostapi:bnbhostapi, 21 | } 22 | -------------------------------------------------------------------------------- /examples/getCalendar.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.getCalendar('18412320') 4 | .then(function(calendar){ 5 | console.log(calendar); 6 | }).catch(function(err){ 7 | console.log('error', err); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/getListings.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.getListings() 4 | .each(function(listing){ 5 | bnbhostapi.getListing(listing['id']) 6 | .then(function(listing_detailed){ 7 | console.log(listing_detailed); 8 | }).catch(function(err){ 9 | console.log('error', err); 10 | }); 11 | }).catch(function(err){ 12 | console.log('error', error); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/getMessages.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.getMessageThreads(50,0,false) 4 | .each(function(message){ 5 | console.log(message.id + ',' + message.other_user.first_name); 6 | }) 7 | .catch(function(err){ 8 | console.log(err); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/getPayouts.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.getPayouts(true). 4 | each(function(payout){ 5 | bnbhostapi.getReservation(payout['reservation']['confirmation_code']) 6 | .then(function(reservation){ 7 | console.log(reservation); 8 | }).catch(function(err){ 9 | console.log('error', err); 10 | }); 11 | }).catch(function(err){ 12 | console.log('error', err); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/getReservation.js: -------------------------------------------------------------------------------- 1 | /** See get examples/getPayouts.js **/ 2 | -------------------------------------------------------------------------------- /examples/getUser.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.getUser('32703781') 4 | .then(function(user){ 5 | console.log(user); 6 | }).catch(function(err){ 7 | console.log('error', error); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/login.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.login() 4 | .then(function(oauth_token){ 5 | console.log(oauth_token); 6 | }).catch(function(err){ 7 | console.log('error', err); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/postCalendar.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.postCalendar('18412320', '2018-12-31', 555, true, true) 4 | .then(function(cal_op){ 5 | console.log(cal_op.calendar_operation.days); 6 | }).catch(function(err){ 7 | console.log('error', err); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/sendMessage.js: -------------------------------------------------------------------------------- 1 | var bnbhostapi = require('../bnbhostapi'); 2 | 3 | bnbhostapi.sendMessage("335989904", "test from api") 4 | .then(function(message){ 5 | console.log(message); 6 | }).catch(function(err){ 7 | console.log('error', err); 8 | }); 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bnbhostapi", 3 | "version": "1.0.6", 4 | "description": "This is a Node JS wrapper to Airbnb's API Endpoints for hosts.", 5 | "main": "bnbhostapi.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/davidplappert/bnbhostapi.git" 12 | }, 13 | "keywords": [ 14 | "airbnb", 15 | "api", 16 | "host", 17 | "node" 18 | ], 19 | "author": "David Plappert", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/davidplappert/bnbhostapi/issues" 23 | }, 24 | "homepage": "https://github.com/davidplappert/bnbhostapi#readme", 25 | "dependencies": { 26 | "bluebird": "^3.5.1", 27 | "request": "^2.83.0" 28 | } 29 | } 30 | --------------------------------------------------------------------------------