Introduction
This documentation covers the different ways you can integrate with the Quantum Suites Booking Engine. If you need assistance, we provide a full integration service. Contact us at: hello@quantumsuites.me
Before you start, you will need:
- A Quantum Suites Account
- Your public API key. This key is NOT secret and will be visible to your end users in URLs, so do not worry about keeping it private.
- You can get your API key on your Settings Page once you log in.
After you've got that, you're ready to integrate. There are three ways to integrate:
-
Basic Integration
Pros:
- No programming needed
- Can be used with any website because you simply link to our reservation process.
- Even works with no website; you can just email or text links to your customers to enable them to book if you wish.
- You can be up and going right now.
Cons:
- No customization of the process
- No branding - generic appearance
- Minimal search features and no cross-promotion with your other units.
-
Custom Integration
Pros:
- You control the whole process and presentation.
- Embed it in your website, make it look branded and "part of" your user experience.
- Enable advanced search features on your site and easily cross-promote your units; if one unit is booked, you can easily set up your site to direct customers to similar available units.
- Incredibly flexible
Cons:
- A light amount of programming may be required. We provide some copy/paste-able examples, but it may be difficult for someone to set up without assistance.
- Might not work with all hosting providers. Some basic hosting providers do not allow you to add custom code to your websites.
-
Use Our Integration Plugins
Pros:
- Easy integration with common platforms
- Almost as full featured as a custom integration, with minimal or no programming required.
- The best of both options
Cons:
- Requires installation of a plugin or custom module on your site. Most providers will allow this, but some may not.
- Only works if you're using one of the supported platforms. See the Integration Plugins section below for a list of supported platforms.
Basic Integration
The basic integration can be used by anyone. Once you have created your account and set up a unit, you can find the URL for the booking page for your units on this screen: Units List
You can use these links wherever and however you like. On your website, in emails, over text messages, it's all good.
You can also set up bookings for your customers by going to one of the links yourself, entering the customer's requested dates and number of guests, and submitting the form. The checkout screen's URL can be copy and pasted, then sent to your customer, to direct the customer straight to the end of the process.
If you wish to test this process without charging your credit card, you can use Stripe's Test Mode API Keys in your user settings to test the process.
Stripe has a list of test payment methods you can use while in test mode. Just remember to put your live API keys back when you are done trying it out!
Custom Integration
Custom integrations enable you to use our API to build your own integration. You have full control over how things are displayed and the overall user experience. However, this control also means it is a more difficult path.
We currently provide two API libraries; one for Javascript and one for PHP. Some Javascript is required to get this to work; Stripe's credit card intake process, used by our system, is powered by Javascript.
So, unfortunately, the PHP library cannot be used exclusively to power all features available. However, it can be used to power search and pricing which may can give your users a faster and better user experience.
Or, if you prefer, all features can be powered by the Javascript library with no PHP required whatsoever. It all depends on what makes the most sense in your particular situation.
Lifecycle of the Transaction
This section describes the lifecycle of the customer's transaction with your website. In other words, the flow that the user is expected to go through.
-
First, the user will arrive at your site. You may either present them your units directly and allow them to click on them for more details and booking, and/or you may want to allow them to search for availability based on their desired checkin / checkout dates.
-
If you want to allow people to search, then you will probably want to use the
getAvailability
call in either the PHP or the Javascript libraries. This search can then be used to direct the customer to a page with details about your unit. -
From the detail page, you will want to use the
getPricing
call in either the PHP or the Javascript libraries to get the final price of the unit. This can be used to display a checkout page. -
The checkout page will need the user to "login". The login is actually an email sent by Quantum Suites with a verification code in it. They will enter this verification code on your site to get a code to complete checkout.
-
Your checkout page will receive the code sent via "login", and validate the code. Validating the code will return a Stripe customer ID which can be used to book the unit.
-
Then you present the user the option to book the unit. If they chose to continue, you can present them with a Stripe form. Their reservation will be held for 10 minutes.
-
After the have successfully booked the unit, we will automatically redirect them to your contract with the house rules in order for them to agree to it and complete their booking.
Importance of Unit URLs
When setting up a unit on Quantum Suites, you will there is a field for configuring the "URL for Unit Details" under the "Integrations" panel. This URL should be the URL on your site which will display details about the unit -- photos and such.
Quantum Suites uses this URL as 'connective tissue'
between itself and your site. When you query units,
such as with getAvailabilities
, you will
receive that URL as part of the results so that you
can direct your customers to the detail page.
Additionally, you can use unitFromUrl
to look up a Quantum Suites Unit ID based on your
URL. It is recommended that you cache the Unit ID
as it won't change unless you delete and re-create
the unit in QSB.
Javascript API
Our Javascript API requires jQuery; almost any version of jQuery will work, as it is used in the most basic ways possible. In the future, we will try to remove this requirement if there is a demand to do so. Many sites, such as WordPress, already use jQuery and so our plugin should work with whatever jQuery is already there.
Right now, we do not have NPM support; again, this is something we can change if there is demand for it.
Here's some sample include code to set up our plugin:
<!-- Include jQuery if you aren't already using it -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- Stripe is only needed on the checkout page -->
<script src="https://js.stripe.com/v3/"></script>
<!-- And the Quantum Suites API itself -->
<script src="https://qsb.quantumsuites.mejs/qsb.js"></script>
Our library provides the QSB class. It can be initalized with your API key (see the introduction section) like this:
<script>
var qsb = new QSB('Your QuatumSuites Public API Key');
</script>
Once initialized, there are a number of methods you can use to query or book units.
Common Conventions
Most functions in the Javascript API work based on
Ajax callbacks. As such, most of them take a
success_callback
and an
error_callback
parameter. These
callbacks are always optional, but usually
success_callback must be set to something in order
for an action to happen after data is fetched.
success_callback
will be called
on a successful call, and it will be passed a
single parameter returning the results of the
operation (i.e. the return value of the Ajax call).
error_callback
will be called
on any kind of failure. This callback is passed
straight to the jQuery.ajax call's 'error'
parameter, and thus you can read the full
documentation of what is passed into it on
jQuery's API documentation site
here.
There are only two likely reasons for error; if https://QuantumSuites.me isn't reachable at the time of the call, or if there is a misconfiguration such as an invalid Quantum Suites API key being used.
"Stripe Format" is referred to in this documentation for prices. Stripe only uses integers in prices; so $19.58 would be represented as 1958 in "Stripe Format". Anything mentioned as being in "Stripe Format" will need to be divided by 100 in order to get a decimal number for display to the end user.
Available Methods
qsb.getLocations (
- callback: success_callback,
- callback: error_callback
)
This method fetches available unit cities and
states/provinces from the API. Once it is
fetched, the location data is cached in
qsb.locations
; subsequent
calls will use this cache instead of re-fetching
from the QSB API server.
success_callback
will be passed
the following object structure:
{
"NC": [
"Cary",
"Raleigh",
...
],
"VA": [
"Lynchburg",
"Richmond",
...
],
...
}
Where the object has a property for each state or province code the host has units in, and each property is a list array of cities in that state where units are located.
This data is provided alphabetically sorted.
qsb.bindStateCitySelect(
- string/element/jQuery: state_select,
- string/element/jQuery: city_select,
- callback: success_callback,
- callback: onchange_callback,
- callback: error_callback
)
Frequently, one will want to make a progressive pair of select boxes where your potential guest will first choose a state and then choose the city. This call sets up a pair of select boxes and does the Ajax getLocations query so that you do not have to.
To use this, you need to place two select boxes in your HTML somewhere. The select boxes do not need to have anything in them; whatever is in them will be replaced when the location data is loaded from the Quantum Suites Booking Engine.
state_select
and
city_select
should both be either
a string with a jQuery compatible selector, a DOM
element object, or a jQuery object that already has
the select element loaded. These should be
empty <select>
elements.
success_callback
is called after
the location data has been loaded and both select
boxes have been configured. Nothing is passed
to it. This is usually used to reveal elements that
are hidden during loading. If you wish to access
the loaded location data, you can access it
via the property qsb.locations
.
onchange_callback
is called after
the 'state' select box has been changed.
bindStateCitySelect will bind a change handler to
the state_select box, and this callback allows you
to chain something after state has been selected
and city has been updated.
error_callback
is passed to
getLocations directly and functions as noted in the
Common Conventions section above.
qsb.getAvailability (
- string: from,
- string: to,
- string/integer: num_guests,
- string: state,
- string: city,
- callback: success_callback,
- callback: error_callback
)
This call is basically the unit search. It gets unit availabilities for start/end dates "from" and "to", for the indicated number of guests. State and city may optionally be provided to narrow down the results further.
from
and to
should
be strings containing dates formated either
"month/day/year" or "year-month-day"; either format is
understood. Four digit years should be used, however
0 padding the month and day are not required.
"2023-4-9" and "9/4/2023" are acceptable date formats
as an example.
num_guests
should either be an
integer or a string containing an integer. This
is the number of guests in the party. QSB does
not distinguish between children/infants and
adult guests at this time.
state
can either be a two-character
state code as obtained from getLocations, or it
can be an empty string to not filter by state.
city
can be either a city string
as obtained from getLocations, or it can be an
empty string to not filter by city.
success_callback
is optional,
and if provided, will be run with the following
data structure as its only parameter:
[
{
"id": "uuid based ID for unit",
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"neighborhood": some brief text description about the location
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
...
]
Some notes about this return structure:
- Most of these fields are set in the QSB unit editor. Title, description, url, max_guests, num_bedrooms, num_bathrooms, type, square_feet, neighborhood, and bed_info are directly powered by what is put in the unit editor.
- price is a price estimate and should not be presented as a final price; it doesn't include fees and taxes. This is the estimated total for the stay.
- nights is a count of the number of nights between the 'from' and 'to' dates, and is the total nights of the stay.
- price_per_night is a simple division of price by nights to get a nightly rate. It is just an estimate value as well, not factoring in taxes or fees.
- latitude and longitude are derived from the address you provide in the QSB unit editor. The resolution is intentionally low; if you use this to render a pin on a map, that pin will be somewhere within a couple miles of the house and not an exact location.
If invalid paramters are provided to the search, for example a date that does not exist or isn't properly formatted, you will get an error structure back instead:
{
"error": true,
"message": "a helpful message"
}
If your user interface does not allow users to input invalid parameters -- for example, you use date pickers and don't allow arbitrary entry of random data -- you should never receive an error. However, if you do, please note that QSB will give a "200 OK" HTTP status but return the above error object.
As a final note, qsb.availability
is set with the return value of getAvailability
regardless of if success_callback is provided
or not. This is not cached,
so subsequenty calls to getAvailability will
re-send the Ajax request.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.getAvailability (
- string: from,
- string: to,
- string/integer: num_guests,
- string: query,
- string: center,
- callback: success_callback,
- callback: error_callback
)
This call is a twist on getAvailability. Similar to the first call, it gets unit availabilities for start/end dates "from" and "to", for the indicated number of guests. The difference is that we will use the HERE geocoding API to resolve 'query' and return results sorted by distance to the located point.
from
and to
should
be strings containing dates formated either
"month/day/year" or "year-month-day"; either format is
understood. Four digit years should be used, however
0 padding the month and day are not required.
"2023-4-9" and "9/4/2023" are acceptable date formats
as an example.
num_guests
should either be an
integer or a string containing an integer. This
is the number of guests in the party. QSB does
not distinguish between children/infants and
adult guests at this time.
query
is a string; it can be anything,
be it a point of interest or a specific address. It
is very flexible and most queries will return some
kind of search.
center
is a latitude and longitude
point in the string format "lat,lng" such as
"35.9050059,-78.7749791". This 'centers' the
search near that point, so that you are less
likely to get results outside of the state
or even country that your units are in.
success_callback
is optional,
and if provided, will be run with the following
data structure as its only parameter:
{
found: {
// results from HERE API, documented here:
https://www.here.com/docs/bundle/geocoding-and-search-api-developer-guide/page/topics-api/code-geocode-spatial-reference.html
},
results: [
{
"id": "uuid based ID for unit",
"title": "unit title",
"distance": distance in meters to location
"description": "a brief description",
"url": "a URL for more information",
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"neighborhood": some brief text description about the location
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
...
]
}
Some notes about this return structure:
- Most of these fields are set in the QSB unit editor. Title, description, url, max_guests, num_bedrooms, num_bathrooms, type, square_feet, neighborhood, and bed_info are directly powered by what is put in the unit editor.
- price is a price estimate and should not be presented as a final price; it doesn't include fees and taxes. This is the estimated total for the stay.
- nights is a count of the number of nights between the 'from' and 'to' dates, and is the total nights of the stay.
- price_per_night is a simple division of price by nights to get a nightly rate. It is just an estimate value as well, not factoring in taxes or fees.
- latitude and longitude are derived from the address you provide in the QSB unit editor. The resolution is intentionally low; if you use this to render a pin on a map, that pin will be somewhere within a couple miles of the house and not an exact location.
If invalid paramters are provided to the search, for example a date that does not exist or isn't properly formatted, you will get an error structure back instead:
{
"error": true,
"message": "a helpful message"
}
If your user interface does not allow users to input invalid parameters -- for example, you use date pickers and don't allow arbitrary entry of random data -- you should never receive an error. However, if you do, please note that QSB will give a "200 OK" HTTP status but return the above error object.
As a final note, qsb.availability
is set with the return value of getAvailability
regardless of if success_callback is provided
or not. This is not cached,
so subsequenty calls to getAvailability will
re-send the Ajax request.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.loginUser(
- string: email,
- string: unit_host_id,
- callback: success_callback,
- callback: error_callback
)
In order for a user to book a unit, they have
to be "logged in". This call will cause QSB
to send an email to the email address provided.
That email will contain a code which you will
in turn pass to validateUser
to
validate them and confirm the login.
email
is the address where we
will send their code. This is rate-limited so
it cannot be used for SPAM.
unit_host_id
is the unit we're booking's
host ID. This comes from getPricing, or if all the
units on your site belong to the same user, you can
just hard-code it to your Quantum Suites API user.
success_callback
will receive
a single parameter of the form:
{
"message": "some message",
"success": true if success, false if failed, message has error
}
'message' is safe to display to the user, and showing them the message is recommended as the error may be informative. This call will always return 200 unless you provided an incorrect QuantumSuites API key.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.validateUser (
- string: email,
- string/integer: code,
- callback: success_callback,
- callback: error_callback
)
loginUser
will send the user an
email with a 6 digit code in it. This call
takes the user's email address and that 6 digit
code, and validates them.
email
is the email that the code
was sent to; it should be the same as what was
passed to loginUser
code
is either an integer or
a string containing an integer with the six
digit code.
success_callback
will be
passed a single parameter with the following
object:
{
"message": "some message",
"success": true if success, false if failed, message has error
"stripe_customer": stripe customer ID string (if success)
}
'message' is usually irrelevant if this call is successful, but it will have an error message if something went wrong (such as an invalid code).
'stripe_customer' is their Stripe customer_id and is safe to reveal, unencrypted, to the user. You may store this in a cookie or some session variable if you wish, but that is not required.
'stripe_customer' is needed to book the unit,
using bookUnit
'message' is safe to display to the user, and showing them the message is recommended as the error may be informative. This call will always return 200 unless you provided an incorrect QuantumSuites API key.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.bookUnit(
- string: unit_id,
- string: from,
- string: to,
- string/integer: num_guests,
- string/integer: dogs,
- string/integer: cats,
- string: customer_id,
- string: city,
- string: state,
- callback: success_callback,
- callback: error_callback
)
This call actually creates a reservation in the system. However, the reservation isn't confirmed until payment is completed.
When you call this, you will receive a Stripe "client_secret" that can be used to present a Stripe payment form. We provide examples of this in the examples section.
unit_id
is a UUID-format string
as received from getAvailabilities
or unitFromUrl
.
from
and to
are strings containing dates in the format
described by getAvailabilities
.
num_guests
is either an integer
or string containing integer number of guests
staying at the property.
dogs
is either an integer
or string containing integer number of dogs
staying at the property. This may be blank
or 0.
cats
is either an integer
or string containing integer number of cats
or other non-dog animals requiring a special
deposit
staying at the property. This may be blank
or 0.
customer_id
is the value
obtained from validateUser
.
city
and state
should be the unit's city and state as obtained
from getAvailabilities
. In a pinch,
these can be blank strings; the purpose of passing
these is to automatically query for alternative
units if the unit was booked out from under the
customer during the checkout process.
success_callback
will be passed
a single parameter. It can return one of three
things. If we were able to place the reservation
successfully, it will receive:
{
'available' => true,
'client_secret' => Stripe client secret for payment intent
'expires' => expiration UNIX timestamp, in seconds
'contract_url' => URL to send the customer to sign contract
AFTER payment is done. Use this as the
stripe return URL.
}
If the unit was booked while the customer was going through the checkout process, you will instead receive:
{
"available": false,
"alternatives": [
// same structure as 'getAvailability'
]
}
In case of an error, which would be if, for instance, the dates are invalid, you will receive this instead. If your form is properly validating user input, this should never happen.
{
"error": true,
"message": "a helpful message"
}
This call will always return a 200 status code unless provided an invalid API key.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.getNextAvailability (
- string/integer: nights,
- string/integer: num_guests,
- string: state,
- string: city,
- callback: success_callback,
- callback: error_callback
)
This call is used to fetch available units based
on a number of days rather than specific dates.
Specifically, it returns the next availabilities
of all your units for a stay of 'nights
'
number of nights.
nights
is the number of nights of
availability required as an integer or string
containing integer.
num_guests
is the number of guests
staying as an integer or string containing integer.
state
contains a 2 letter state or
province code as returned from getLocations. It
is optional, if left off, all states will be
queried.
city
contains a city from getLocations.
It is optional, if left off, all cities will be
queried.
success_callback
will be called on
completion and, for this call, is required as
you won't get any data from this if ignored.
The structure passed to the callback will be:
[
{
"id": "uuid based ID for unit",
"title": "unit title",
"url": "a URL for more information",
"neighborhood": some brief text description about the location,
"nights_available": Number of nights available
"starting": date the nights_available starts,
"city": city,
"province": province
"num_bedrooms": number of bedrooms,
"num_bathrooms": number of bathrooms
},
...
]
If invalid paramters are passed, you can receive an error object. You should validate the user's input rather than allow this to happen.
{
"error": true,
"message": a helpful message but maybe not the best for the user
}
This call will always return a 200 status code unless provided an invalid API key.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.getPricing(
- string: unit_id,
- string: from,
- string: to,
- string/integer: num_guests,
- string/integer: num_dogs,
- string/integer: num_cats,
- string: city,
- string: state,
- string: customer_id,
- callback: success_callback,
- callback: error_callback
)
This call produces a full final price for a unit, completely broken down with taxes and fees. It is designed to be called when displaying the checkout screen.
unit_id
is a UUID-format string
as received from getAvailabilities
or unitFromUrl
.
from
and to
are strings containing dates in the format
described by getAvailabilities
.
num_guests
is either an integer
or string containing integer number of guests
staying at the property.
dogs
is either an integer
or string containing integer number of dogs
staying at the property. This may be blank
or 0.
cats
is either an integer
or string containing integer number of cats
or other non-dog animals requiring a special
deposit
staying at the property. This may be blank
or 0.
city
and state
should be the unit's city and state as obtained
from getAvailabilities
. In a pinch,
these can be blank strings; the purpose of passing
these is to automatically query for alternative
units if the unit was booked out from under the
customer during the checkout process.
customer_id
is the value
obtained from validateUser
. It is
optional and may be an empty string or false
if you don't have it. The reasoning for passing
it here is so that, if a customer has a booking
in progress, that booking won't count against
availability if the getPricing is called during
the checkout process.
success_callback
will be passed
a single parameter. It can return one of three
things. If the unit is still available, you
will receive:
{
"available": true,
"num_nights": integer number of nights in the stay,
"pay_schedule": [
{
"charge_on": "YYYY-MM-DD",
"amount": integer in stripe format
"amount_tax": integer in stripe format
},
...
],
"totals": {
"num_nights": integer number of nights of the stay
"cat_deposit": integer amount in 'stripe' format
"pet_fee": integer amount in 'stripe' format
"authorize": integer amount in 'stripe' format
"charge": integer amount in 'stripe' format
"charge_tax": integer amount in 'stripe' format
"monthly": integer amount in 'stripe' format
"monthly_tax": integer amount in 'stripe' format
"last_month": integer amount in 'stripe' format
"last_month_tax": integer amount in 'stripe' format
"total_cost": integer amount in 'stripe' format
"total_tax": integer amount in 'stripe' format
"utility_fee": integer amount in 'stripe' format
},
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"price_per_night": price per night in 'stripe' format,
"neighborhood": some brief text description about the location
"unit_host_id": the host ID of the unit owner, used by login
"stripe_publish_key": the stripe key to use to book the unit
}
Note about "pay_schedule"; this is a list of payments that will be made in the future, if the user has booked a reservation longer than 28 days and will thus be paying some kind of periodic rent instead of paying for the entire reservation up front.
Therefore, for reservations 28 days or shorter, this will be an empty list.
If the unit is not available because someone booked it before this call was made, you will receive:
{
"available": false,
"next_available": { Next time the unit requested is available
"available_start": "YYYY-MM-DD" date unit is available
"available_checkout": "YYYY-MM-DD" proposed checkout date
"available_nights": integer night count, or null if calendar is open.
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"neighborhood": some brief text description about the location,
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
"alternatives": [
// same structure as 'getAvailability'
]
}
next_available is details about the next time the unit will be available, and 'alternatives' returns a list similar to getAvailability of other units that are available for the same dates and number of guests.
The following structure will be returned if invalid inputs are provided (i.e. incorrect dates). Ideally, you should validate user input to prevent this:
{
"error": true,
"message": a helpful message but maybe not the best for the user
}
This call will always return a 200 status code unless provided an invalid API key.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.unitFromUrl (
- string: url,
- callback: success_callback,
- callback: error_callback
)
Unit URLs are used to glue your site and Quantum Suites together seamlessly. For more details about our recommendations here, see the section above.
The url
parameter should be the end
portion of a URL. For instance, if your unit
detail page has the url:
http://yoursite.com/units/detail/1234.html
You could pass '1234.html' to the url
parameter and receive the QSB unit ID assuming
the unit URL is configured correctly in the QSB
back-end.
success_callback
will receive the
following structure:
[
{
"id": the unit ID
"url": the URL we have on record
"title": the title we have for the unit
},
...
]
Note that it is technically possible to match multiple URLs in the case that what you pass isn't sufficiently distinct. Thus, this returns a list with all matches. Of course, you may also match nothing and receive an empty list. This call will never generate an error.
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
qsb.blockedDates(
- string: unit_id,
- callback: success_callback,
- callback: error_callback
)
Sometimes it is desirable to know which dates are already booked; for instance, when presenting a calendar widget for a unit, you may wish to have dates that are not available to be already blocked.
This call will return a list with start/end date
pairs for a provided unit_id
.
success_callback will receive:
[
[start_date, end_date],
[start_date, end_date],
...
]
This may be an empty list if the unit has no blocks on the calendar. It will never return an error assuming unit_id is valid (if it is not valid, you will receive a 404 error).
error_callback
is passed to
jQuery.ajax directly and functions as noted in the
Common Conventions section above.
PHP API
Our PHP API uses the PHP cURL extension. This extension is enabled by default on most web hosts. At the moment, we do not have our library set up to work with Composer or any other package system, but we will seek to improve that in the future.
You can grab our PHP library here.
Our library provides the QSB object, which can be initialized thusly with your API key (see the introduction section):
require_once ('qsb.php');
$qsb = new QSB('Your API Key');
Once initialized, you can use a variety of methods as described below.
Available Methods
$qsb->getLocations ()
This method fetches available unit cities and states/provinces from the API. We recommend caching the return value of this as it will rarely change. The return value will be a PHP dictionary array such as:
{
"NC": [
"Cary",
"Raleigh",
...
],
"VA": [
"Lynchburg",
"Richmond",
...
],
...
}
Where the object has a property for each state or province code the host has units in, and each property is a list array of cities in that state where units are located.
This data is provided alphabetically sorted.
$qsb->getAvailability (
- string: from,
- string: to,
- string/integer: num_guests,
- string: state,
- string: city
)
This call is basically the unit search. It gets unit availabilities for start/end dates "from" and "to", for the indicated number of guests. State and city may optionally be provided to narrow down the results further.
from
and to
should
be strings containing dates formated either
"month/day/year" or "year-month-day"; either format is
understood. Four digit years should be used, however
0 padding the month and day are not required.
"2023-4-9" and "9/4/2023" are acceptable date formats
as an example.
num_guests
should either be an
integer or a string containing an integer. This
is the number of guests in the party. QSB does
not distinguish between children/infants and
adult guests at this time.
state
can either be a two-character
state code as obtained from getLocations, or it
can be an empty string to not filter by state.
city
can be either a city string
as obtained from getLocations, or it can be an
empty string to not filter by city.
A PHP associative array is returned:
[
{
"id": "uuid based ID for unit",
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"neighborhood": some brief text description about the location
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
...
]
Some notes about this return structure:
- Most of these fields are set in the QSB unit editor. Title, description, url, max_guests, num_bedrooms, num_bathrooms, type, square_feet, neighborhood, and bed_info are directly powered by what is put in the unit editor.
- price is a price estimate and should not be presented as a final price; it doesn't include fees and taxes. This is the estimated total for the stay.
- nights is a count of the number of nights between the 'from' and 'to' dates, and is the total nights of the stay.
- price_per_night is a simple division of price by nights to get a nightly rate. It is just an estimate value as well, not factoring in taxes or fees.
- latitude and longitude are derived from the address you provide in the QSB unit editor. The resolution is intentionally low; if you use this to render a pin on a map, that pin will be somewhere within a couple miles of the house and not an exact location.
If invalid paramters are provided to the search, for example a date that does not exist or isn't properly formatted, you will get an error structure back instead:
{
"error": true,
"message": "a helpful message"
}
If your user interface does not allow users to input invalid parameters -- for example, you use date pickers and don't allow arbitrary entry of random data -- you should never receive an error. However, if you do, please note that QSB will give a "200 OK" HTTP status but return the above error object.
qsb.getAvailability (
- string: from,
- string: to,
- string/integer: num_guests,
- string: query,
- string: center
)
This call is a twist on getAvailability. Similar to the first call, it gets unit availabilities for start/end dates "from" and "to", for the indicated number of guests. The difference is that we will use the HERE geocoding API to resolve 'query' and return results sorted by distance to the located point.
from
and to
should
be strings containing dates formated either
"month/day/year" or "year-month-day"; either format is
understood. Four digit years should be used, however
0 padding the month and day are not required.
"2023-4-9" and "9/4/2023" are acceptable date formats
as an example.
num_guests
should either be an
integer or a string containing an integer. This
is the number of guests in the party. QSB does
not distinguish between children/infants and
adult guests at this time.
query
is a string; it can be anything,
be it a point of interest or a specific address. It
is very flexible and most queries will return some
kind of search.
center
is a latitude and longitude
point in the string format "lat,lng" such as
"35.9050059,-78.7749791". This 'centers' the
search near that point, so that you are less
likely to get results outside of the state
or even country that your units are in.
A PHP associative array is returned:
{
found: {
// results from HERE API, documented here:
https://www.here.com/docs/bundle/geocoding-and-search-api-developer-guide/page/topics-api/code-geocode-spatial-reference.html
},
results: [
{
"id": "uuid based ID for unit",
"title": "unit title",
"distance": distance in meters to location
"description": "a brief description",
"url": "a URL for more information",
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"neighborhood": some brief text description about the location
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
...
]
}
Some notes about this return structure:
- Most of these fields are set in the QSB unit editor. Title, description, url, max_guests, num_bedrooms, num_bathrooms, type, square_feet, neighborhood, and bed_info are directly powered by what is put in the unit editor.
- price is a price estimate and should not be presented as a final price; it doesn't include fees and taxes. This is the estimated total for the stay.
- nights is a count of the number of nights between the 'from' and 'to' dates, and is the total nights of the stay.
- price_per_night is a simple division of price by nights to get a nightly rate. It is just an estimate value as well, not factoring in taxes or fees.
- latitude and longitude are derived from the address you provide in the QSB unit editor. The resolution is intentionally low; if you use this to render a pin on a map, that pin will be somewhere within a couple miles of the house and not an exact location.
If invalid paramters are provided to the search, for example a date that does not exist or isn't properly formatted, you will get an error structure back instead:
{
"error": true,
"message": "a helpful message"
}
If your user interface does not allow users to input invalid parameters -- for example, you use date pickers and don't allow arbitrary entry of random data -- you should never receive an error. However, if you do, please note that QSB will give a "200 OK" HTTP status but return the above error object.
$qsb->loginUser(
- string: email
- string: unit_host_id
)
In order for a user to book a unit, they have
to be "logged in". This call will cause QSB
to send an email to the email address provided.
That email will contain a code which you will
in turn pass to validateUser
to
validate them and confirm the login.
email
is the address where we
will send their code. This is rate-limited so
it cannot be used for SPAM.
unit_host_id
is the unit we're booking's
host ID. This comes from getPricing, or if all the
units on your site belong to the same user, you can
just hard-code it to your Quantum Suites API user.
You will receive the following associative array as a return:
{
"message": "some message",
"success": true if success, false if failed, message has error
}
'message' is safe to display to the user, and showing them the message is recommended as the error may be informative. This call will always return 200 unless you provided an incorrect QuantumSuites API key.
$qsb->validateUser (
- string: email,
- string/integer: code
)
loginUser
will send the user an
email with a 6 digit code in it. This call
takes the user's email address and that 6 digit
code, and validates them.
email
is the email that the code
was sent to; it should be the same as what was
passed to loginUser
code
is either an integer or
a string containing an integer with the six
digit code.
You will receive the following associative array as a return:
{
"message": "some message",
"success": true if success, false if failed, message has error
"stripe_customer": stripe customer ID string (if success)
}
'message' is usually irrelevant if this call is successful, but it will have an error message if something went wrong (such as an invalid code).
'stripe_customer' is their Stripe customer_id and is safe to reveal, unencrypted, to the user. You may store this in a cookie or some session variable if you wish, but that is not required.
'stripe_customer' is needed to book the unit,
using bookUnit
'message' is safe to display to the user, and showing them the message is recommended as the error may be informative. This call will always return 200 unless you provided an incorrect QuantumSuites API key.
$qsb->bookUnit(
- string: unit_id,
- string: from,
- string: to,
- string/integer: num_guests,
- string/integer: dogs,
- string/integer: cats,
- string: customer_id,
- string: city,
- string: state
)
This call actually creates a reservation in the system. However, the reservation isn't confirmed until payment is completed.
When you call this, you will receive a Stripe "client_secret" that can be used to present a Stripe payment form. We provide examples of this in the examples section.
unit_id
is a UUID-format string
as received from getAvailabilities
or unitFromUrl
.
from
and to
are strings containing dates in the format
described by getAvailabilities
.
num_guests
is either an integer
or string containing integer number of guests
staying at the property.
dogs
is either an integer
or string containing integer number of dogs
staying at the property. This may be blank
or 0.
cats
is either an integer
or string containing integer number of cats
or other non-dog animals requiring a special
deposit
staying at the property. This may be blank
or 0.
customer_id
is the value
obtained from validateUser
.
city
and state
should be the unit's city and state as obtained
from getAvailabilities
. In a pinch,
these can be blank strings; the purpose of passing
these is to automatically query for alternative
units if the unit was booked out from under the
customer during the checkout process.
This call will return the following as an associative array:
{
'available' => true,
'client_secret' => Stripe client secret for payment intent
'expires' => expiration UNIX timestamp, in seconds
'contract_url' => URL to send the customer to sign contract
AFTER payment is done. Use this as the
stripe return URL.
}
If the unit was booked while the customer was going through the checkout process, you will instead receive:
{
"available": false,
"alternatives": [
// same structure as 'getAvailability'
]
}
In case of an error, which would be if, for instance, the dates are invalid, you will receive this instead. If your form is properly validating user input, this should never happen.
{
"error": true,
"message": "a helpful message"
}
This call will always return a 200 status code unless provided an invalid API key.
$qsb->getNextAvailability (
- string/integer: nights,
- string/integer: num_guests,
- string: state,
- string: city
)
This call is used to fetch available units based
on a number of days rather than specific dates.
Specifically, it returns the next availabilities
of all your units for a stay of 'nights
'
number of nights.
nights
is the number of nights of
availability required as an integer or string
containing integer.
num_guests
is the number of guests
staying as an integer or string containing integer.
state
contains a 2 letter state or
province code as returned from getLocations. It
is optional, if left off, all states will be
queried.
city
contains a city from getLocations.
It is optional, if left off, all cities will be
queried.
You will receive the following associative array as a return:
[
{
"id": "uuid based ID for unit",
"title": "unit title",
"url": "a URL for more information",
"neighborhood": some brief text description about the location,
"nights_available": Number of nights available
"starting": date the nights_available starts,
"city": city,
"province": province
"num_bedrooms": number of bedrooms,
"num_bathrooms": number of bathrooms
},
...
]
If invalid paramters are passed, you can receive an error object. You should validate the user's input rather than allow this to happen.
{
"error": true,
"message": a helpful message but maybe not the best for the user
}
This call will always return a 200 status code unless provided an invalid API key.
$qsb->getPricing(
- string: unit_id,
- string: from,
- string: to,
- string/integer: num_guests,
- string/integer: num_dogs,
- string/integer: num_cats,
- string: city,
- string: state,
- string: customer_id
)
This call produces a full final price for a unit, completely broken down with taxes and fees. It is designed to be called when displaying the checkout screen.
unit_id
is a UUID-format string
as received from getAvailabilities
or unitFromUrl
.
from
and to
are strings containing dates in the format
described by getAvailabilities
.
num_guests
is either an integer
or string containing integer number of guests
staying at the property.
dogs
is either an integer
or string containing integer number of dogs
staying at the property. This may be blank
or 0.
cats
is either an integer
or string containing integer number of cats
or other non-dog animals requiring a special
deposit
staying at the property. This may be blank
or 0.
city
and state
should be the unit's city and state as obtained
from getAvailabilities
. In a pinch,
these can be blank strings; the purpose of passing
these is to automatically query for alternative
units if the unit was booked out from under the
customer during the checkout process.
customer_id
is the value
obtained from validateUser
. It is
optional and may be an empty string or false
if you don't have it. The reasoning for passing
it here is so that, if a customer has a booking
in progress, that booking won't count against
availability if the getPricing is called during
the checkout process.
You will receive the following associative array as a return:
{
"available": true,
"num_nights": integer number of nights in the stay,
"pay_schedule": [
{
"charge_on": "YYYY-MM-DD",
"amount": integer in stripe format
"amount_tax": integer in stripe format
},
...
],
"totals": {
"num_nights": integer number of nights of the stay
"cat_deposit": integer amount in 'stripe' format
"pet_fee": integer amount in 'stripe' format
"authorize": integer amount in 'stripe' format
"charge": integer amount in 'stripe' format
"charge_tax": integer amount in 'stripe' format
"monthly": integer amount in 'stripe' format
"monthly_tax": integer amount in 'stripe' format
"last_month": integer amount in 'stripe' format
"last_month_tax": integer amount in 'stripe' format
"total_cost": integer amount in 'stripe' format
"total_tax": integer amount in 'stripe' format
"utility_fee": integer amount in 'stripe' format
},
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"price_per_night": price per night in 'stripe' format,
"neighborhood": some brief text description about the location
"unit_host_id": the host ID of the unit owner, used by login
"stripe_publish_key": the stripe key to use to book the unit
}
Note about "pay_schedule"; this is a list of payments that will be made in the future, if the user has booked a reservation longer than 28 days and will thus be paying some kind of periodic rent instead of paying for the entire reservation up front.
Therefore, for reservations 28 days or shorter, this will be an empty list.
If the unit is not available because someone booked it before this call was made, you will receive:
{
"available": false,
"next_available": { Next time the unit requested is available
"available_start": "YYYY-MM-DD" date unit is available
"available_checkout": "YYYY-MM-DD" proposed checkout date
"available_nights": integer night count, or null if calendar is open.
"title": "unit title",
"description": "a brief description",
"url": "a URL for more information",
"neighborhood": some brief text description about the location,
"max_guests": maximum number of guests,
"num_bedrooms": integer number of bedrooms,
"num_bathrooms": decimal number of bedrooms,
"latitude": latitude geo location
"longitude": longitude geo location,
"type": This will be a text such as "House", "Apartment", etc.,
"square_feet": size of unit in square feet
"price": integer price in 'stripe' format
"nights": number of nights,
"price_per_night": price per night in 'stripe' format,
"bed_info": [
{
"King": integer,
"Queen": integer,
... (keys will be missing if 0)
},
...
]
},
"alternatives": [
// same structure as 'getAvailability'
]
}
next_available is details about the next time the unit will be available, and 'alternatives' returns a list similar to getAvailability of other units that are available for the same dates and number of guests.
The following structure will be returned if invalid inputs are provided (i.e. incorrect dates). Ideally, you should validate user input to prevent this:
{
"error": true,
"message": a helpful message but maybe not the best for the user
}
This call will always return a 200 status code unless provided an invalid API key.
$qsb->unitFromUrl (
- string: url
)
Unit URLs are used to glue your site and Quantum Suites together seamlessly. For more details about our recommendations here, see the section above.
The url
parameter should be the end
portion of a URL. For instance, if your unit
detail page has the url:
http://yoursite.com/units/detail/1234.html
You could pass '1234.html' to the url
parameter and receive the QSB unit ID assuming
the unit URL is configured correctly in the QSB
back-end.
You will receive the following array as a return:
[
{
"id": the unit ID
"url": the URL we have on record
"title": the title we have for the unit
},
...
]
Note that it is technically possible to match multiple URLs in the case that what you pass isn't sufficiently distinct. Thus, this returns a list with all matches. Of course, you may also match nothing and receive an empty list. This call will never generate an error.
$qsb->blockedDates(
- string: unit_id
)
Sometimes it is desirable to know which dates are already booked; for instance, when presenting a calendar widget for a unit, you may wish to have dates that are not available to be already blocked.
This call will return a list with start/end date
pairs for a provided unit_id
.
You will receive the following array as a return:
[
[start_date, end_date],
[start_date, end_date],
...
]
This may be an empty list if the unit has no blocks on the calendar. It will never return an error assuming unit_id is valid (if it is not valid, you will receive a 404 error).
Samples
JavaScript Sample
This is a work in progress.
PHP Sample
This will be provided at a later date; we recommend reviewing the JavaScript sample. The best integrations use both, with PHP doing calls such as getLocation that can be cached locally and JavaScript handling the user interface bits.
Testing
In the future, we would like to be able to provide a sandbox vs. a live environment. However, at this time, we are unable to do that.
As such, the only way to test is to replace your live Stripe credentials with test Stripe credentials. This means that bookings will be put on your calendar when you do tests; be aware of this and clean up your test bookings.
We recommend you test using dates far in the future (1 year in the future, specifically) to avoid potentially blocking customer bookings.
See the following links for more information:
- QSB Account Settings - Go here to change your API key settings.
- Stripe Documentation about getting test API keys
- Stripe Test Payment Methods
Integration Plugins
In the near future, this section will have information about plugins that will allow easy integrations with commonly used systems such as WordPress.
Right now, we're still in the launch stages of the Quantum Suites Booking Engine, and as such, we have not yet released any of our integrations.
However, we are planning on releasing a WordPress plugin in the near future. Feel free to contact us if you have an interest in an integration with some specific system, and we will consider building it. Or we may be able to add you to a beta program if it is a system we are already working on.
Contact us at: hello@quantumsuites.me