
Mindbody Affiliate API
The Mindbody Affiliate API gives your users the ability to find, book, and pay for fitness and wellness classes offered by businesses within the Mindbody Network. Whether you want to offer your users a “Guest Checkout” experience or facilitate repeat bookings, you will find this API easy to use and capable of providing delightful experiences to your users.
The Affiliate API is an HTTP-based API, so it works with any language that has an HTTP library. Requests use standard HTTP verbs such as GET
, POST
, and DELETE
. JSON is returned and accepted by all endpoints. The API documentation uses the JSON data types defined by W3Schools. The resource documentation describes requests and responses in detail for each endpoint.
Example Use Cases
- Let guest users find, book, and pay for classes
- Let authenticated users find, book, and pay for classes
- Show a user the state of their account, including bookings, purchases, and passes
Data Model
Getting Started
- Contact us to become a Mindbody Network Partner.
- Get your API key, client key, and client secret for our development environment.
- Begin coding your integration and download our Postman zip file.
- Use your Sandbox Mindbody Demo Businesses to develop and test your integration.
- Complete your integration.
- Perform a Launch Checklist Review with Mindbody.
- Get your API key, client key, and client secret for production and increase your rate limits.
Designing a UX for Consumers
At Mindbody, we believe in designing delightful experiences for our end-users. This guide provides insights into the mind of wellness-seekers so that you can use the Affiliate API to provide your wellness-seekers with the best experience possible.
A Matter of Convenience
The primary concern of wellness-seekers when trying to find wellness services is convenience. Users are more likely to establish a relationship with a business that:
- Is affordable
- Is on their way to or from work/home
- Consistently has openings in its classes
- Offers classes at times outside their working hours
The Search for Wellness
Use GET Locations with either an
address
orlatitude
/longitude
query parameter to set the geographical center of the location search.
Location is paramount. Users want to search for services in their immediate area, or in a specific area, generally near their work or school. We recommend allowing users to search in both ways.
Allow your users to change the size of their search area by altering the
radius
query parameter being passed to GET Locations.
Because “convenience” does not mean the same thing for each user, we also recommend allowing your users to increase or decrease the size of the area they are searching for wellness services.
Use the
searchText
query parameter on the GET Locations call to search by category or business name.
When users are trying to find a new wellness service, they usually try to search by category. They may use categorical terms such as:
- Yoga
- Pilates
- Cycling
- Crossfit
- Barre
- Dance
- Etc.
On occasion, users may know the name of the business they want to find but are not sure of its location. This might happen, for instance, if they were referred to the business by a friend.
There are some users who do not necessarily know what they are looking for; they just want to discover the available wellness services in or around their area.
Collect information about the business from the
subscriber
object returned from the GET Locations call.
Common things users want to know about a business include:
- Name
- Street address and business description
- Reviews
- Business photos (such as pictures of the floor-space, front desk, etc.)
- Whether or not the location offers introductory (one-time) deals
Collect information about the classes offered at the location by using the GET Classes call.
Once a user selects a location, their focus is likely to shift to the classes offered by that location. Typically, users are most concerned with a class’s:
- Start and end times
- Name and description
- Staff description/biographies
- Staff photos
- Difficulty level
Do a location search via GET Locations behind the scenes, then use GET Classes for each of the locations near your user to create an interface where users select classes before locations.
Depending on your interface, a user might select a class before they look at the class’s location. When this happens, they are less concerned with the business, but they may still check to see if the location appeals to them. We recommend presenting the same location information as outlined above for this workflow.
Pricing
Use GET PricingOptions to find information about the pricing that will pay for a specific class.
Use GET PricingOptions (by location) to show all pricing options offered at a location, regardless of the location’s offered classes.
Some users are on the hunt for the best pricing/service combination. Of primary importance when showing pricing is the:
- Price
- Name
- Description
- Number of sessions
If a pricing option returned from GET PricingOptions has a
userRestrictions
value ofIntroductoryOfferFirstTimeCustomerOfPricingOption
orIntroductoryOfferFirstTimeCustomerAtBusiness
, it is a deal.
When showing deals (discounted, one-time-purchase pricing options) to users, it is important to contrast the price of the deal with the class’s normal price. Otherwise, the benefit of purchasing the deal is not immediately apparent to the user.
Call POST Booking when you user is ready to book into a class.
Peer Opinion
Check the
ratings
object returned from GET Locations to find the rating information associated with a specific location.
Reviews and ratings for wellness businesses can play a secondary role in the user’s search for services. Users are more likely to trust a new business if they can see a large number of reviews and most of the reviews are positive.
As your users begin taking classes, you may want to begin capturing your own information about the classes to create enhanced experiences for future users. Things you may be interested in capturing include:
- What kind of music do they play in this class?
- Is this class good for beginners?
- What is the room temperature?
- What is the teacher like?
- Is there more cardio or strength training in this class?
- What classes are trending in the area?
- What pricing options are most frequently purchased in the area?
Additional Tips
A location’s contact info is stored in the
contactInfo
object returned from the GET Locations call.A business’s cancellation policy can be found in the
cancellationPolicy
returned from the GET Locations call.A business’s refund policy can be found in the
refundPolicy
returned from the GET Locations call.
- Grouping is important when showing information to your wellness-seekers. Make sure that the current date is prominently displayed on your interface, preferably close to your class times. Grouping the date next to class times decreases the cognitive load placed on the user.
- When classes are not bookable by your users, be sure to give them an indication as to why this is the case. It is disconcerting for the user to see a list of unbookable classes without some kind of context as to why they cannot be booked. Recommendations for each indicator are outlined in the Resource documentation.
- Make the business’s contact information very easy to find by displaying it on multiple pages. If users encounter workflows that your app or the Affiliate API do not support, it is important that they have quick access to help.
- Make the business’s cancellation and refund policies very easy to find and display them on multiple pages. Prominently displaying this information will more clearly direct users to the business if they need help with a refund or cancellation.
- Do not sacrifice specificity for brevity. For example, if the user already has a pass on file, do not show their potential class as “free.” Rather, indicate that they already have a valid payment on file that they can use.
If you have any further questions, comments, or insights, please do not hesitate to contact us!
Authentication and Security
Assuming that you encoded the string
"clientKey:clientSecret"
and your API key is"yourAPIKey"
, each of your requests would have headers as demonstrated below.
curl -X GET \
-H "API-Key: yourAPIKey" \
-H "Authorization:Basic Y2xpZW50S2V5OmNsaWVudFNlY3JldA==" \
-A "yourAppName" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/13909/classes"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/13909/classes");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic Y2xpZW50S2V5OmNsaWVudFNlY3JldA==");
request.AddHeader("api-key", "yourAPIKey");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/13909/classes');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic Y2xpZW50S2V5OmNsaWVudFNlY3JldA==',
'api-key' => 'yourAPIKey'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "yourAPIKey",
'authorization': "Basic Y2xpZW50S2V5OmNsaWVudFNlY3JldA=="
}
conn.request("GET", "/affiliate/api/v1/locations/13909/classes", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/13909/classes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = 'yourAPIKey'
request["authorization"] = 'Basic Y2xpZW50S2V5OmNsaWVudFNlY3JldA=='
response = http.request(request)
puts response.read_body
When making a call without an API-Key header, you will receive a 401 HTTP status code and the following error response:
{
"error": {
"errorCode": "14010001",
"errorType": "missingAPIKeyHeader",
"message": "Missing API-Key Header."
}
}
When making a call without an Authorization header, you will receive a 401 HTTP status code and the following error response:
{
"error": {
"errorCode": "14010002",
"errorType": "missingAuthorizationHeader",
"message": "Missing Authorization Header."
}
}
The Affiliate API uses API keys and basic access authentication. Once you have become an approved Mindbody Network Partner, you will receive an API key, a client key, and a client secret. To make a successful API call:
- Pass your API key as an
API-Key
header. - Encode your client key and client secret, then pass the encoded string as an
Authorization
header, preceded by the word “Basic” and a space.
To correctly encode your client key and client secret, concatenate them together separated by a colon, then use a Base64 library to convert them to an encoded string. For example, if your client key is "clientKey"
and your client secret is "clientSecret"
, you will encode the string, "clientKey:clientSecret"
. Once encoded, you would pass the value in an Authorization
header as Basic {yourEncodedClientKeyAndClientSecret}
.
If you make a call and either the API-Key or Authorization header contains an invalid value, you will receive a 401 HTTP status code and an empty response body.
If you have verified that you are using the correct authentication information (according to your account) and you are still receiving a 401, contact our developer support department.
HTTPS
All calls to the Affiliate API must use HTTPS connections, utilizing TLS v1.2 or higher. Any connections made via an older version of TLS are not guaranteed to work correctly.
Your Sandbox Environment
Once you have access to the Affiliate API, Mindbody will create sandboxed business data specific to your integration. This data is fictitious but structured in exactly the same way as a real business. You will have full access to these demo businesses for development and testing purposes; you can experiment with changing their settings and data from our web-base user interface.
For a detailed introduction to managing a business’ settings and data, check out Testing Best Practices.
After you have tested and finalized your integration, Mindbody will give you production access to the location, class, and pricing data in the Mindbody Network for which you have been approved. Unlike sandboxed data, you cannot access live business data via our web-based user interface. When you are ready to go live, contact our developer support team.
Working with Your User Data
The Affiliate API identifies users based on the uniqueUserId
you pass to the POST Booking call. Once you have completed the user’s initial booking, you can use this ID to:
- Create new bookings on a previously purchased pass
- Find account details such as:
- bookings
- purchases
- passes
The uniqueUserId
must:
- Be between 1 and 64 characters in length
- Contain only:
- alphanumeric characters (lowercase)
- _ (underscores)
- - (hyphens)
- ~ (tildes)
- . (periods)
Base URL
https://mb-api.mindbodyonline.com/affiliate/api/v1
Versioning
If Mindbody introduces an API change that breaks preexisting API contracts, we will create a new API version number and provide you with a transition guide.
Current Version: 1
Previous Version: NA
Pagination
Making Requests
Each Affiliate API endpoint will specify whether or not it supports pagination.
Endpoints that support pagination accept maxResults
and offset
query parameters.
maxResults
specifies the maximum number of records you want the call to return. The documentation for each endpoint will call out the accepted maxResults
values for that endpoint.
offset
specifies the number of records you want the call to skip. If offset
is not included in the request, the call does not skip any records.
Understanding Responses
Example of an API call that returns multiple results and supports pagination:
{
"offset": 10,
"maxResults": 10,
"totalResults": 154,
"items": [
{
"field1": "value1"
}
]
}
Example of an API call that returns multiple results but does not support pagination:
{
"items": [
{
"field1": "value1"
}
]
}
Example of an API call that returns a single resource:
{
"field1": "value1"
}
Name | Type | Description |
---|---|---|
offset | number | The number of records skipped over to reach the returned results. |
maxResults | number | The maximum number of records returned in the results. |
totalResults | number | The total number of records found that match the request parameters. |
items | array of objects | Contains the records found by the query. |
Ordering Results
The following example demonstrates how to order passes by their expiration date. The results of this call will show the pass that isexpiring soonest first and the pass that expiring latest last.
curl -X GET \
-A "{yourAppName}" \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes?orderBy=expirationDateTime&order=desc"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes?orderBy=expirationDateTime&order=desc");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes');
$request->setMethod(HTTP_METH_GET);
$request->setQueryData(array(
'orderBy' => 'expirationDateTime',
'order' => 'desc'
));
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/passes?orderBy=expirationDateTime&order=desc", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes?orderBy=expirationDateTime&order=desc")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
Many of the endpoints in the Affiliate API let you order result sets by using the orderBy
and order
query parameters.
orderBy
designates which field orders the results. The documentation for individual endpoints will call out both the default orderBy
field and acceptable values for this parameter.
order
orders the results in ascending or descending order based on the field specified by orderBy
. Acceptable values are either "asc"
or "desc"
. The documentation for each endpoint will call out the default order
value for that endpoint.
Dates and Times
The Affiliate API returns and accepts dates and times in ISO 8601 format as defined by the RFC 339 specification.
In Requests
When you pass dates/times to the API, it treats them as UTC dates and ignores any time zone offset information included in the request. An example of an acceptable format is YYYY-MM-DDThh:mm:ssZ
. You should convert any local date/time ranges you are working with to UTC when querying the API. For example, you would pass January 15th, 2017 at 8:00 AM (PST) to the API as "2017-01-15:T16:00:00Z"
because PST is eight hours behind UTC.
In Responses
The API returns UTC dates/times. For example, a class that happens on January 5th, 2017 at 2:15PM (EST) would be represented by "2017-01-05T19:15:00Z"
because EST is five hours behind UTC. All date/time pairs are returned in the format YYYY-MM-DDTHH:mm:ssZ
.
We recommend that you give users a visual cue when they find classes outside their current time zone. You can convert the class’s start and end times into their local time zone by using the location.olsonTimeZone
property returned on all class objects.
For example, John Smith lives in California but is flying to New York today for vacation. He wants to find a fitness class near his hotel. If he finds a class on your app that takes place at 7:00 PM, it is unclear whether it is eastern time or pacific; the class’s time is ambiguous, so John cannot know for sure when it takes place. For clarity, consider appending “(EST)”, “(local time)”, or “(7 hours from now)” to the class time.
Rate Limits
Rate limits are in place to ensure fast response times and stability. Too many requests within a small period of time may be rejected. If you need increased rate limits, please contact your account manager.
There are several strategies you can employ to avoid hitting your rate limits. Consider caching location and class information (we recommend caching for no longer than 24 hours).
Resource ID Conventions
When fetching information for a specific location, all IDs returned are unique within the scope of that location’s subscriber. For example, a class ID at a subscriber called “ACME Yoga” will always be unique, regardless of the number of locations that “ACME Yoga” has. However, when looking at classes at a different subscriber, for example “ACME Pilates”, you may see the same class IDs. Those are different classes, even though they might share IDs.
Subscriber, location, pass, purchase, and booking IDs are always globally unique.
Errors
In the Affiliate API, HTTP response codes indicate the status of a request.
- Codes in the 200 range indicate success.
- Codes in the 400 range indicate errors in the provided information (e.g., a required parameter was omitted, a parameter violated its minimum or maximum constraint, etc.).
- Codes in the 500 range indicate errors from our servers. Please contact us immediately if you receive a 500 error.
{
"error": {
"errorCode": "14000001",
"errorType": "missingAPIKeyHeader",
"message": "Missing API-Key Header."
}
}
The Affiliate API returns errors for many reasons. We recommend writing code that gracefully handles all possible errors as documented for each endpoint.
In addition to HTTP codes, the API returns a JSON error response object (as demonstrated on the right).
Name | Type | Description |
---|---|---|
errorCode | string | A code for the specific error returned. You can safely parse these values to numbers. |
errorType | string | A categorical code indicating which aspect of the request was invalid. |
message | string | A brief message explaining why you received the error. |
Testing Best Practices
The data returned from the Affiliate API can and does change. Mindbody subscribers are constantly changing their classes, pricing, and locations – often as part of their marketing strategy, to increase their brand presence, or to expand their business.
As you develop your integration with the API, it is important that you test your app’s ability to correctly handle changes in the data. This is especially true when a change breaks a workflow. Email us to request a testing guide that will walk you through altering your Mindbody Demo Business Data so you can make sure your app is smoothly handling data changes.
Tutorials
Find services, pay, and book
Summary
This tutorial demonstrates how to use the Affiliate API to create an experience in which your user:
- Looks through Mindbody subscriber locations in their area
- Selects the location in which they are interested
- Chooses a class they want to book at the selected location
- Selects the pricing option they want to purchase to reconcile the class
- Enters their credit card and contact information
- Books into the class using their newly purchased pricing option
Workflow
Call GET Locations and allow your user to select a location. At a minimum, store the location’s:
id
olsonTimeZone
subscriber.id
subscriber.creditCardTypesAccepted
subscriber.hasLiabilityWaiver
Using the stored location’s
id
, call GET Classes. Allow your user to select a class and store itsid
.Using the selected class’ stored
id
, call GET PricingOptions. Allow your user to select a pricing option, and store itsid
.-
Call POST Booking using the stored location, class, and pricing option IDs.
We recommend using the stored
subscriber.creditCardTypesAccepted
(from Step 1 above) to ensure your users are not trying to use invalid credit cards.Upon receiving a successful booking response, we recommend displaying the booking’s:
class.name
class.startDateTime
class.endDateTime
class.registrationNotes
staff.firstName
subscriber.name
location.name
location.contactInfo
(formatted appropriately)
-
This step is optional, but recommended because it will ease the user’s front desk experience at the subscriber and in your app.
Check the
hasLiabilityWaiver
bit that we stored in Step 1. If it istrue
, call GET LiabilityWaivers and collect the user’s signature as a PNG image. Next, call POST LiabilityWaivers to save the user’s signature to the subscriber.If possible, we recommend implementing your system so it tracks which users have already signed waivers for specific subscribers. Doing so allows you to request a signature from users only when the liability waiver text has changed or it’s their first time booking at the subscriber, rather than asking for a signature each time they book.
Book services with a pass
Summary
This tutorial demonstrates how to use the Affiliate API to create an experience in which your user:
- Looks through Mindbody subscriber locations in their area
- Selects the location in which they are interested
- Chooses a class they want to book at the selected location
- Selects a previously purchased pass
- Books into the class using their chosen pass
Workflow
Call GET Passes and store the results.
Call GET Locations and allow your user to select a location. At a minimum, store the location’s:
id
olsonTimeZone
subscriber.id
subscriber.hasLiabilityWaiver
Using the stored location’s
id
, call GET Classes.Assuming passes were returned and stored in Step 1, check if any will reconcile classes at the selected location. When a pass and class’s
subscriber.id
match, and the class’sserviceCategoryIds
array contains the pass’serviceCategoryId
, this indicates that the pass will reconcile the class. You can alter your display to indicate that the user already has a pass on file that would cover a visit to the matched class(es). For example, you may choose to display the word “Book” for classes that can be reconciled by the user’s passes.Allow your user to select a class and store its
id
.-
Call POST Booking using the stored location, class, and pass IDs.
Upon receiving a successful booking response, we recommend displaying the booking’s:
class.name
class.startDateTime
class.endDateTime
class.registrationNotes
staff.firstName
subscriber.name
location.name
location.contactInfo
(formatted appropriately)
-
This step is optional, but recommended because it will ease the user’s front desk experience at the subscriber and in your app.
Check the
hasLiabilityWaiver
bit that we stored in Step 1. If it istrue
, call GET LiabilityWaivers and collect the user’s signature as a PNG image. Next, call POST LiabilityWaivers to save the user’s signature to the subscriber.If possible, we recommend implementing your system so it tracks which users have already signed waivers for specific subscribers. Doing so allows you to request a signature from users only when the liability waiver text has changed or it’s their first time booking at the subscriber, rather than asking for a signature each time they book.
Find services paid for by a pass
Summary
This tutorial demonstrates how to use the Affiliate API to create an experience in which your user:
- Chooses a pass they want to use to book a class
- Is shown a list of available classes that the pass will pay for
- Selects the class they would like to book
- Books into the chosen class using the selected pass
Workflow
-
Call GET Passes and allow your user to select a pass for which they want to find classes. At a minimum, store the selected pass’s:
id
serviceCategoryId
purchase.id
expirationDateTime
-
Call GET Purchase by ID using the pass’ stored
purchase.id
, then store the purchase’slocation.id
. -
Call GET Classes using the purchase’s stored
location.id
.Pass the stored
serviceCategoryId
, in the call’sserviceCategoryIds
query parameter.If it is not
null
, pass the storedexpirationDateTime
, in the call’sendDateTime
query parameter. If it isnull
, do not pass theendDateTime
query parameter.Allow your user to select a class and store its
id
. -
Call POST Booking using the stored location, class, and pass IDs.
Upon receiving a successful booking response, we recommend displaying the booking’s:
class.name
class.startDateTime
class.endDateTime
class.registrationNotes
staff.firstName
subscriber.name
location.name
location.contactInfo
(formatted appropriately)
Resources
Locations
Subscribers
Subscribers are companies that use Mindbody to manage their businesses. A subscriber can make their class and pricing information available in the Affiliate API by joining the Mindbody Network.
Locations
A location is the physical space where classes are held. Each subscriber must set up at least one location, but they could have multiple. For example, “ACME Pilates” might have studios on both South 1st Street and North 22nd Street. Each location will have a unique address.
GET
Getting a location by geo coordinates:
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?latitude=35.247137&longitude=-120.643215"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?latitude=35.247137&longitude=-120.643215");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations');
$request->setMethod(HTTP_METH_GET);
$request->setQueryData(array(
'latitude' => '35.247137',
'longitude' => '-120.643215'
));
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations?latitude=35.247137&longitude=-120.643215", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?latitude=35.247137&longitude=-120.643215")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
Getting a location by address:
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?address=4051%20Broad%20St%2C%20San%20Luis%20Obispo%2C%20CA%2C%2093401"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?address=4051%20Broad%20St%2C%20San%20Luis%20Obispo%2C%20CA%2C%2093401");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations');
$request->setMethod(HTTP_METH_GET);
$request->setQueryData(array(
'address' => '4051 Broad St, San Luis Obispo, CA, 93401'
));
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/affiliate/api/v1/locations?address=4051%20Broad%20St%2C%20San%20Luis%20Obispo%2C%20CA%2C%2093401", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations?address=4051%20Broad%20St%2C%20San%20Luis%20Obispo%2C%20CA%2C%2093401")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations
This endpoint searches for locations in the following ways:
- By
address
- By
longitude
andlatitude
- By
countryCode
- By
locationId
- By
subscriberId
- By
searchText
Some of the above search methods cannot be mixed. See query parameters on this call for more information. If none of the above query parameters are passed, all locations are returned.
You can retrieve a specific location either by utilizing the locationId
query parameter or by calling GET (by ID).
Pagination
This endpoint supports pagination.
Best Practices
- Use when looking for locations near a specific address.
- Use when looking for locations near a geo-location (latitude/longitude pair).
- Use to retrieve a specific location’s details.
- Use when searching for locations associated with a specific keyword or search phrase.
- Use when pulling the cancellation or refund policy text for a specific subscriber.
- Use before calling GET Classes.
- Use the returned
subscriber.creditCardTypesAccepted
to indicate the kinds of credit cards the subscriber accepts. We recommend showing this information to your users prior to allowing them to complete a booking.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
Query Parameters
Name | Type | Description |
---|---|---|
latitude Optional: When omitted, you must also omit longitude . |
number | The latitude portion of the latitude/longitude pair that acts as the geographical center of your location search. When searching based on geographical coordinates, you must use both latitude and longitude and may additionally use the following query parameters:
|
longitude Optional: When omitted, you must also omit latitude . |
number | The longitude portion of the latitude/longitude pair that acts as the geographical center of your location search. When searching based on geographical coordinates, you must use longitude with latitude and may additionally use the following query parameters:
|
address Optional |
string | The address that acts as the geographical center of your location search. You can use the city or postal code portion of the address if a full address is not available. You can use address with the following query parameters:
?address=4051 Broad St,San Luis Obispo,CA,93401 ?address=San Luis Obispo,CA ?address=93401 max length: 100 |
radius Optional |
number | Used with the geographical center of your search, radius sets the area (in miles) for the search. When you pass radius , make sure you also pass either an address , or a latitude /longitude pair, otherwise the call will fail.default: 15 | max: 60 | min: 0 |
locationId Optional |
number | Filters the results down to the single location identified by this ID. You can use locationId with any other valid query parameter combination, or by itself. This is the id property on the location object returned from this call and the location.id property returned from other calls in the API. |
subscriberId Optional |
number | Filters the results down to locations that belong to the subscriber identified by this ID. You can use subscriberId with any other valid query parameter combination, or by itself. This is the subscriber.id property returned on most calls in the API, including this one. |
countryCode Optional |
string | Filters results to only show locations within the specified country (based on the ISO ALPHA-2 country code specification). Accepted Values:
countryCode with any other valid query parameter combination, or by itself. |
searchText Optional |
string | Filters the results down to locations where the passed in searchText matches text in the location name and subscriber name. Locations where the searchText matches the category of services that the business is likely to offer are also returned. Please note that when searching by searchText , we make a good attempt at matching businesses and services, but the locations included in the result set are not guaranteed to offer the services being searched for.Example Values:
searchText with any other valid query parameter combination, or by itself. |
maxResults Optional |
number | Sets the maximum number of records returned in the results.default: 500 | max: 1000 | min: 0 |
offset Optional |
number | Sets the number of records skipped over to reach the returned results.default: 0 | min: 0 |
orderBy Optional |
string | Designates which field in the response body orders the results. Accepted Values:
orderBy query parameter with your request. |
order Optional |
string | Orders the results in ascending or descending order based on the field specified by orderBy .Accepted Values:
|
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": 13540,
"name": "ACME Yoga",
"description": null,
"olsonTimeZone": "America/Los_Angeles",
"ratings": {
"total": 150,
"average": 4.32
},
"subscriber": {
"id": 1354158,
"name": "ACME Yoga",
"description": null,
"website": "http://www.acmeyoga.com",
"cancellationPolicy": null,
"refundPolicy": null,
"locale": "en-US",
"hasLiabilityWaiver": false,
"imageUrls": [],
"creditCardTypesAccepted": [
"Visa",
"MasterCard",
"Discover",
"AmericanExpress"
]
},
"contactInfo": {
"phone": "5551231234",
"streetAddress": "4051 Broad St Suite 220",
"city": "San Luis Obispo",
"stateCode": "CA",
"postalCode": "93401",
"countryCode": "US",
"longitude": -120.642881,
"latitude": 35.247461
},
"distance": 1.23
}
],
"offset": 0,
"maxResults": 1,
"totalResults": 79
}
Name | Type | Description |
---|---|---|
id | number | The location’s globally unique ID. |
name | string | The location’s name. |
description | string | The location’s subscriber-configured description. |
olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
ratings | object | Contains rating information for the location. |
ratings.total | number | The total number of times users have rated classes at this location. |
ratings.average | number | The average quality rating (out of 5 stars, e.g., 3.26 ). |
subscriber | object | Contains information about the subscriber to whom the location belongs. |
subscriber.id | number | The subscriber’s globally unique ID. |
subscriber.name | string | The subscriber’s name. |
subscriber.description | string | The subscriber’s business description. |
subscriber.website | string | The URL for the subscriber’s main website. |
subscriber.cancellationPolicy | string | The subscriber’s cancellation policy text. |
subscriber.refundPolicy | string | The subscriber’s refund policy text. |
subscriber.locale | string | The primary spoken language used at the subscriber, represented by a C# culture string (e.g., "en-US" for United States English). Possible cultures. |
subscriber.hasLiabilityWaiver | boolean | When true , indicates that the subscriber requires new users to agree to a liability waiver. We recommend prompting your users to sign a liability waiver for locations where this is true to ease their front-desk experience at the subscriber. See GET LiabilityWaivers and POST LiabilityWaivers.When false , indicates that the subscriber does not require new users to agree to a liability waiver. |
subscriber.imageURLs | array of objects | Contains information about the different sizes of images available for the subscriber’s logo. |
subscriber.imageURLs.size | string | The size of the image. Possible Values:
|
subscriber.imageURLs.url | string | The URL for the image. |
subscriber.creditCardTypesAccepted | array of strings | Which credit card types the subscriber will accept as a form of payment. Possible Values:
|
contactInfo | object | Contains contact information for the location. |
contactInfo.phone | string | The location’s phone number. |
contactInfo.streetAddress | string | The street address portion of the location’s address. |
contactInfo.city | string | The city portion of the location’s address. |
contactInfo.stateCode | string | The state code portion of the location’s address (e.g. "CA" for California in the USA.). |
contactInfo.postalCode | string | The postal code portion of the location’s address. |
contactInfo.countryCode | string | The location’s country (e.g., "US" ). This value will always be an ISO ALPHA-2 Code. |
contactInfo.longitude | number | The location’s longitude. |
contactInfo.latitude | number | The location’s latitude. |
distance | number | The distance in miles between the location and the geographical center of your search. This value may be null if a geographical center could not be calculated for your search. |
Errors
Example Error:
{
"error": {
"errorCode": "14000004",
"errorType": "invalidParameter",
"message": "The following parameter is invalid: radius."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
400 | 14000006 | invalidParameterCombination | Returned if you pass a query parameter with another query parameter that cannot be used with the first (e.g., passing a lat/long pair as well as an address). |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by ID)
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}
This endpoint finds and returns the single location associated with the passed ID.
Pagination
This endpoint does not support pagination.
Best Practices
- Use when looking for full location details when you already have the location’s ID.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | Returns the single location identified by this ID. This is the id property on the location object returned from this call and the location.id property returned from other calls in the API. |
Response
Partial example of response content structure:
{
"olsonTimeZone": "America/Los_Angeles",
"id": 13540,
...
}
This response object is the same as the objects contained in the items
field in the GET Locations response . View that documentation for detailed information about the response object’s fields.
Errors
Example Error:
{
"error": {
"errorCode": "14040001",
"errorType": "locationNotFound",
"message": "Location not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
Classes
Classes
Classes have specific dates, start and end times, and represent actual events that your users can book into. Each class is taught by a staff member and has a capacity that defines the maximum number of bookings the class will accept.
Class types differentiate classes within a subscriber. For example, “Vinyasa Yoga” and “Hatha Yoga” are two different class types. A subscriber may schedule a class type multiple times. For example, ACME Yoga, has scheduled a “Vinyasa Yoga,” class on Mondays from 10:00 AM to 11:00 AM as well as on Wednesdays from 2:00 PM to 3:00 PM; both of these classes have the same class type.
A class refers to an individual occurrence of a class type. For example, the “Vinyasa Yoga” class scheduled on Monday, 9/19/2016 from 10:00 AM to 11:00 AM is a single class.
Available capacity refers to the number of remaining bookings available for a specific class. For example, if a class allows a maximum of 10 bookings and currently has 6, the class has an available capacity of 4.
Service Categories
Service categories are groups of classes that share pricing options. As part of the set-up process, subscribers assign each class to a specific service category. Once assigned, a class’ service category does not change.
By default, classes can only be reconciled either through the purchase of a new pricing option or by reusing a previously purchased pass. However, subscribers can relate service categories so that a pricing option in one category can pay for classes in another. Each class’ serviceCategoryIds
property contains all service categories that will pay for the class.
GET
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("API-Key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'API-Key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'API-Key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}/classes", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["API-Key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes
This endpoint gets classes that are taking place at a specific location.
You can retrieve a specific class by calling GET (by ID).
Pagination
This endpoint supports pagination.
Best Practices
- Use after calling GET Locations to find all classes offered at the selected location.
- Use before calling GET PricingOptions and GET Passes.
- Use to fetch class details for a specific class.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | Specifies from which location to fetch classes. This is the id property on the location object returned from this call and the location.id property returned from other calls in the API. |
Query Parameters
Name | Type | Description |
---|---|---|
startDateTime Optional |
string | The UTC date/time that sets the beginning of the time-frame within which you are searching for classes. Classes with UTC start times on or after this date/time are returned. See Dates and Times in Requests for more information.default: now | max: 365 days from now | min: now |
endDateTime Optional |
string | The UTC date/time that sets the end of the time-frame within which you are searching for classes. Classes with UTC start times before this date/time are returned. See Dates and Times in Requests for more information.default: 14 days from now | max: 365 days from now | min: now |
classTypeId Optional |
number | Filters the results down to classes that have the specified class type. This is the typeId property on the class object returned from this call. |
staffLastName Optional |
string | Filters the results down to classes with staff members whose last names match this parameter. This is the staff.lastName property in the class object returned from this call. This parameter does not filter on assistant teacher names.max length: 50 |
availableForBooking Optional: When omitted, the results contain all classes regardless of current capacity. |
boolean | When true , filters the results to classes:
false , filters the results to classes:
|
serviceCategoryIds Optional |
string | Filters the results down to classes paid for by the specified service category or categories. Pass multiple service categories in a comma-separated list. For example, ?serviceCategoryIds=24,8 would return classes paid for by service category 24, service category 8, or both.Classes paid for by related service categories will also be returned in this call. For example, if a service category with an ID of 5 pays for a service category with an ID of 9, ?serviceCategoryIds=9 will return classes that can be paid for by either category.The serviceCategoryIds property on the class object returned from this call contains this value. |
maxResults Optional |
number | Sets the maximum number of records returned in the results.default: 500 | max: 1000 | min: 0 |
offset Optional |
number | Sets the number of records skipped over to reach the returned results.default: 0 | min: 0 |
orderBy Optional |
string | Designates which field in the response body orders the results. Accepted Values:
|
order Optional |
string | Orders the results in ascending or descending order based on the field specified by orderBy .Accepted Values:
|
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": 31034,
"typeId": 7,
"name": "Beginning Hatha Yoga",
"description": "A gentle introduction to the Hatha practice.",
"classSize": 15,
"availableCapacity": 7,
"registrationNotes": "Bring a yoga mat and a large bottle of water.",
"startDateTime": "2016-12-15T17:00:00Z",
"endDateTime": "2016-12-15T18:00:00Z",
"assistantNames": [],
"roomName": null,
"bookingWindow": {
"startDateTime": "2016-12-15T14:13:26.737Z",
"endDateTime": "2016-12-15T17:00:00Z",
"dailyStartTime": null,
"dailyEndTime": null
},
"cancellationsAllowed": true,
"cancellationWindowEndTime": "2016-12-15T16:00:00Z",
"serviceCategoryIds": [
25
],
"sessionsDeducted": 1,
"availability": {
"statusCode": 10,
"message": "Available for booking"
},
"price": {
"lowest": 15,
"highest": 80
},
"classImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_large.jpg?v=23"
},
{
"size": "Unscaled",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_.jpg?v=23"
}
],
"staff": {
"id": 3,
"firstName": "Thomas",
"lastName": "Jones",
"gender": "Male",
"staffImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/staff/3_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/staff/3_large.jpg?v=23"
},
{
"size": "Mobile",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/staff/3_mobile.jpg?v=23"
}
],
"bio": null
},
"location": {
"id": 12856,
"name": "ACME Yoga",
"olsonTimeZone": "America/Los_Angeles",
"subscriber": {
"id": 13548,
"name": "ACME Yoga"
}
},
"category": {
"id": 194,
"name": "Yoga"
},
"subCategory": {
"id": 199,
"name": "Hatha"
},
"isVirtual": true
}
],
"offset": 0,
"maxResults": 1,
"totalResults": 213
}
Name | Type | Description |
---|---|---|
id | number | The ID for this specific class at the current subscriber; the class’s ID. |
typeId | number | The ID for the class’s class type within the current subscriber. |
name | string | The name of the class. |
description | string | The class’ subscriber-configured description. This string contains HTML. |
classSize | number | The class’s capacity; how many total bookings the class accepts. |
availableCapacity | number | The number of remaining bookings for the class (e.g., A class with a classSize of 10 with 6 spaces booked has an availableCapacity of 4.). This value will be -9999 if the subscriber has configured classes to hide this information from users. |
registrationNotes | string | Special notes or instructions the subscriber wants to relay to users who are booking the class. For example, "Make sure you bring a sweat towel and bottle of water!" . |
startDateTime | string | The date and time when the class starts (in UTC). See Dates and Times in Responses for more information. |
endDateTime | string | The date and time when the class ends (in UTC). See Dates and Times in Responses for more information. |
assistantNames | array of strings | Contains the names of all assistant teachers assigned to the class. |
roomName | string | The name of the room where the class is held (e.g., "Sun Room" or "Studio A" ). This value might be null if the subscriber has hidden class rooms. |
bookingWindow | object | Contains information that specifies when users can book the class. If the current time is outside this booking window, you can use this information to give users a time-frame when they will be able to make bookings. |
bookingWindow.startDateTime | string | The date and time after which the class accepts bookings (in UTC). See Dates and Times in Responses for more information. |
bookingWindow.endDateTime | string | The date and time after which the class no longer accepts bookings (in UTC). See Dates and Times in Responses for more information. |
bookingWindow.dailyStartTime | string | The time of day after which the class accepts bookings (in UTC). See Dates and Times in Responses for more information. |
bookingWindow.dailyEndTime | string | The time of day after which bookings are no longer accepted for the class (in UTC). See Dates and Times in Responses for more information. |
cancellationsAllowed | boolean | When true , indicates that the subscriber allows users to cancel bookings they make in this class, up to the cancellationWindowEndTime .When false , indicates that the subscriber does not allow users to cancel bookings they make in this class, regardless of the cancellationWindowEndTime . |
cancellationWindowEndTime | string | The date and time after which cancellations can no longer be made for bookings in the class (in UTC). See Dates and Times in Responses for more information. |
serviceCategoryIds | array of numbers | The IDs of the service categories whose pricing options can pay for the class. |
sessionsDeducted | number | The number of sessions consumed from passes used to pay for this class. For example, a subscriber may configure their system so that a 30-minute class consumes 1 session while a 60-minute class consumes 2 sessions. |
availability | object | Contains information that determines whether or not users can book the class. You may want to display classes that are not currently available for booking to your users, because they may be available for booking at another date or time. If you do show unavailable classes, it is a very important design best practice to give a visual indicator to your users so they know that the class is not currently available for booking. |
availability.statusCode | number | A numeric code identifying whether or not users can book the class. Possible Values:
|
availability.message | string | A short, informative message that describes why the above statusCode was returned. |
price | object | Contains pricing information for the class. |
price.lowest | number | The cost of the least expensive pricing option that can pay for this class. |
price.highest | number | The cost of the most expensive pricing option that can pay for this class. |
classImageURLs | array of objects | Contains information about the different sizes of images available for the class. |
classImageURLs.size | string | The size of the image. Possible Values:
|
classImageURLs.url | string | The URL for the image. |
staff | object | Contains information about the staff member who teaches the class. |
staff.id | number | The staff member’s ID within the current subscriber. |
staff.firstName | string | The staff member’s first name. This value might be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be the staff’s nickname if they have one configured. |
staff.lastName | string | The staff member’s last name. This value will be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be null if the staff member has a nickname configured. |
staff.gender | string | The staff member’s gender. Possible Values:
|
staff.staffImageURLs | array of objects | Contains information about the different sizes of images available for the staff member. |
staff.staffImageURLs.size | string | The size of the image. Possible Values:
|
staff.staffImageURLs.url | string | The URL for the image. |
staff.bio | string | The staff member’s biography. |
location | object | Contains information about the location where the class is taking place. |
location.id | number | The location’s globally unique ID. |
location.name | string | The location’s name. |
location.olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
location.subscriber | object | Contains information about the subscriber to whom the location belongs. |
location.subscriber.id | number | The subscriber’s globally unique ID. |
location.subscriber.name | string | The subscriber’s name. |
category | object | Contains information about the category assigned to the class. Categories are assigned to classes to help further describe the offering and provide a common tag for grouping. |
category.id | number | The category’s ID. |
category.name | string | The category’s name. |
subCategory | object | Contains information about the sub-category assigned to the class. |
subCategory.id | number | The sub-category’s ID. |
subCategory.name | string | The sub-category’s name. |
isVirtual | boolean | When true , indicates that the class supports livestreaming.When false , indicates that the class does not support livestreaming. |
Errors
Example Error:
{
"error": {
"errorCode": "14000004",
"errorType": "invalidParameter",
"message": "The following parameter is invalid: radius."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by ID)
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}/classes/{classId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}
This endpoint finds and returns the single class associated with the passed ID.
Pagination
This endpoint does not support pagination.
Best Practices
- Use to fetch class details for a specific class. You must already have the class’s ID and the class’s location ID.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | Specifies from which location you are fetching the specific class. This is the id property on the location object returned from GET Locations. |
classId | number | Returns the single class identified by this ID. This is the id property on the class object returned from this call and the class.id property returned from other calls in the API. |
Response
Partial example of response content structure:
{
"id": 31034,
"typeId": 7,
...
}
This response object is the same as the objects contained in the items
field in the GET Classes response . View that documentation for detailed information about the response object’s fields.
Errors
Example Error:
{
"error": {
"errorCode": "14040005",
"errorType": "classNotFound",
"message": "Class not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
404 | 14040005 | classNotFound | The classId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
PricingOptions
Pricing Options
When a user pays for a class, they are actually purchasing a pricing option. Once purchased, pricing options become passes on a user’s account, which they can use to book classes. Pricing options can have any number of sessions attached to them (think of a 10-class punch card, only digital). Bookings consume these sessions to mark themselves as paid or reconciled (much like a punch on a punch card).
There are 3 different types of pricing options:
- Drop-in pricing options pay for a single class (they only have one session assigned to them).
- Series pricing options pay for multiple classes (e.g., a “5-class pack”).
- Unlimited pricing options pay for an unlimited number of classes (e.g., a “30 days unlimited”).
A pricing option can pay for bookings that take place between its activation and expiration dates. A subscriber can configure a pricing option’s activation date in 3 different ways:
- On the purchase date - the activation date will be the date when the user purchased the pricing option.
- On the client’s first visit - the pricing option will activate on the same date as the user’s first booking that the pricing option reconciles. Until it is used to reconcile a booking, the activation date will match the purchase date.
- On a set date - the activation date is a specific date (e.g., 12/15/2016) which will not change regardless of purchase or booking dates.
A pricing option’s expiration date is calculated based on its activation date.
GET
Getting pricing options for a class:
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}/pricingOptions"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}/pricingOptions");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}/pricingOptions');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}/classes/{classId}/pricingOptions", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/classes/{classId}/pricingOptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
This endpoint finds pricing options for a specific class.
Pagination
This endpoint does not support pagination.
Best Practices
- Use after fetching classes via the GET Classes call.
- Use before making a POST Booking call.
- Use if the user is not using a pass on their account to pay for their booking.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | Specifies from which location you are fetching the specific class. This is the id property on the location object returned from GET Locations. |
classId | number | Specifies for which class to fetch pricing options. This is the id property on the class object returned from GET Classes. |
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": 5176,
"serviceCategoryId": 25,
"name": "Single Yoga Class",
"type": "DropIn",
"description": null,
"sessionCount": 1,
"subtotal": 15,
"tax": 0.75,
"total": 15.75,
"currencyCode": "USD",
"activationType": "OnPurchaseDate",
"userRestrictions": [
"None"
],
"expirationTimeUnit": "Months",
"expirationTimeUnitValue": 12,
"activationDateTime": "2017-01-15T16:00:00Z",
"expirationDateTime": "2018-01-15T16:00:00Z"
}
]
}
Name | Type | Description |
---|---|---|
id | number | The pricing option’s ID at the current subscriber. |
serviceCategoryId | number | The ID of the service category at the current subscriber to which the pricing option belongs. |
name | string | The pricing option’s name. |
type | string | Describes the type of the pricing option. Possible Values:
|
description | string | The pricing option’s subscriber-configured description. |
sessionCount | number | The number of sessions for which this pricing option will pay. |
subtotal | number | The total cost of the pricing option before applying taxes. |
tax | number | The total cost of taxes for the pricing option. |
total | number | The total cost of the pricing option, including taxes. |
currencyCode | string | A currency code based on the ISO 4217 specification (e.g., "USD" represents the US dollar). |
activationType | string | Specifies the pricing option’s activation type. Possible Values:
|
userRestrictions | array of strings | Specifies whether or not the subscriber restricts the purchasing of this pricing option to users that meet specific criteria. Possible Values:
|
expirationTimeUnit | string | The type of unit used to calculate the pricing option’s expiration date (e.g., this is the “months” in a pricing option that isactive for “12 months”). Possible Values:
expirationTimeUnitValue . |
expirationTimeUnitValue | number | The number of expirationUnits used to calculate the pricing option’s expiration date (e.g., this is the “12” in a pricing option that isactive for “12 months”). This is always used with expirationTimeUnit . |
activationDateTime | string | The date and time after which the pricing option reconciles bookings (in UTC). See Dates and Times in Responses for more information. |
expirationDateTime | string | The date and time after which the pricing option no longer reconciles bookings (in UTC). See Dates and Times in Responses for more information. |
Errors
Example Error:
{
"error": {
"errorCode": "14040005",
"errorType": "classNotFound",
"message": "Class not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
404 | 14040005 | classNotFound | The classId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by location)
Getting pricing options for a location:
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/pricingOptions"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/pricingOptions");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/pricingOptions');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}/pricingOptions", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/pricingOptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/pricingOptions
This endpoint finds pricing options that can be purchased and used at a specific location.
Pagination
This endpoint does not support pagination.
Best Practices
- If you are creating an interface that lets your users shop based on their chosen pricing, use after fetching locations via the GET Locations call.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | Specifies for which location you are fetching pricing options. This is the id property on the location object returned from GET Locations. |
Query Parameters
Name | Type | Description |
---|---|---|
serviceCategoryIds Optional |
string | Filters the results down to pricing options within the specified service category or categories. Pass multiple service categories in a comma-separated list. For example, ?serviceCategoryIds=24,8 would return pricing for both service category 24 and 8.The serviceCategoryId property on the pricing option object returned from this call will match one of the passed values. |
Response
Partial example of response content structure:
{
"items": [
{
"id": 5176,
"serviceCategoryId": 25,
...
}
]
}
This response object is the same as the response returned from GET PricingOptions with one, minor difference.
If a pricing option’s activationType
is OnFirstVisitScheduledWithPass
, both its activationDateTime
and expirationDateTime
will be null
– we cannot calculate these values without knowing which class the user is booking.
You can calculate these values once your user chooses a class.
For example, Jane Doe just used your app to find all pricing available at a location. She chose a “5 pack” pricing option that activates on the user’s first visit, then she continued through the workflow and selected a class that takes place tomorrow at 10:00 AM (UTC). Prior to purchase, you want to show her the time-frame she has to use the pricing option. If the pricing option’s expirationTimeUnit
is "Months"
and its expirationTimeUnitValue
is 6
, you could show its expirationDateTime
as six months from tomorrow.
View the GET PricingOptions response documentation for detailed information about this endpoint’s response object.
Errors
Example Error:
{
"error": {
"errorCode": "14040001",
"errorType": "locationNotFound",
"message": "Location not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
Bookings
Bookings
Users create bookings when they reserve a space in a class. During the booking process and use of POST booking, users can either use their available pass(es) or purchase a new pricing option to reconcile the booking. Once purchased, a pricing option becomes an active pass in the user’s account.
By default, a user cannot book into overlapping classes. For example, Fred Jones might try to book a Yoga and a Pilates class, both of which run from 4:30 to 5:30 on Wednesday. Because Fred cannot be in two places at once, this is not allowed. Subscribers can configure their settings to allow overlapping bookings, but it is not common.
Booking Windows
Subscribers configure booking windows which set restrictions around when users can book into classes. If a user tries to book outside the booking window, the booking will fail. Booking windows apply to all classes within a service category.
As an example, Jane Doe is trying to book a Yoga class for 5:00 PM this evening. If the class’s booking window opened 30 minutes ago, she’s been able to book for a half hour. If the booking window closes in 3 hours, Jane still has that much time to book her class. On the other hand, if the class’s booking window starts in 30 minutes, or if it ended 30 minutes ago, she would not be able to book.
Subscribers can also configure daily booking windows to restrict the time of day before and after which users can make new bookings. Let’s pretend that ACME Yoga set up this restriction so that users can only make new bookings between the hours of 7:00 AM and 10:00 PM each day. If the current time is not between 7:00 AM and 10:00 PM, users cannot make any new bookings regardless of the class’s time.
Cancellations
If a user wants to cancel a booking, they can, but only if the cancellation is valid according to all configured subscriber settings.
When a user cancels a booking, the session used to pay for the booking returns to the pass on the user’s account; no monetary funds are issued to the user. Other users can now book the spot that became available due to the cancellation.
Use the GET Locations call to retrieve a subscriber’s cancellation policy text.
Cancellation Windows
A cancellation window specifies the time frame within which users can cancel bookings. For example, if the cancellation window ends in 30 minutes, a user would not be able to cancel their booking 60 minutes from now. Like booking windows, cancellation windows uniformly apply to all classes in the same service category.
GET
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/bookings", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings
This endpoint returns bookings for the specified user.
You can retrieve a specific booking by calling GET (by ID).
Pagination
This endpoint supports pagination.
Best Practices
- Use when constructing an account status page to show the user a list of their bookings.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
Query Parameters
Name | Type | Description |
---|---|---|
locationId Optional |
number | Filters the results down to the user’s bookings at the location identified by this ID. This is the id property on the location object returned from the GET Locations call and the location.id property returned from other calls in the API. |
subscriberId Optional |
number | Filters the results down to the user’s bookings at the subscriber identified by this ID. This is the subscriber.id property on the location object returned from the GET Locations call. |
maxResults Optional |
number | Sets the maximum number of records returned in the results.default: 20 | max: 100 | min: 0 |
offset Optional |
number | Sets the number of records skipped over to reach the returned results.default: 0 | min: 0 |
orderBy Optional |
string | Designates which field in the response body orders the results. Accepted Values:
|
order Optional |
string | Orders the results in ascending or descending order based on the field specified by orderBy .Accepted Values:
|
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": "f5405d87-46a0-4b48-a384-e26159e130d6",
"bookingDateTime": "2016-12-15T19:51:49.357Z",
"state": "Booked",
"sessionsDeducted": 1,
"pass": {
"id": "4117bed4-615a-40d2-968c-9aac2412c4dd",
"type": "DropIn",
"name": "Single Yoga Class"
},
"class": {
"id": 1234151,
"typeId": 7,
"name": "Beginning Hatha Yoga",
"description": "A gentle introduction to the Hatha practice.",
"registrationNotes": "Bring a yoga mat and a large bottle of water.",
"classImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_large.jpg?v=23"
},
{
"size": "Unscaled",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_.jpg?v=23"
}
],
"startDateTime": "2016-12-15T17:00:00Z",
"endDateTime": "2016-12-15T18:00:00Z",
"assistantNames": [],
"roomName": null,
"cancellationsAllowed": true,
"cancellationWindowEndTime": "2016-12-15T16:00:00Z",
"serviceCategoryIds": [
25
],
"staff": {
"id": 3,
"firstName": "Thomas",
"lastName": "Jones",
"gender": "Male",
"staffImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYogastaff/3_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYogastaff/3_large.jpg?v=23"
},
{
"size": "Mobile",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYogastaff/3_mobile.jpg?v=23"
}
],
"bio": null
},
"location": {
"id": 12856,
"name": "ACME Yoga",
"olsonTimeZone": "America/Los_Angeles",
"subscriber": {
"id": 13548,
"name": "ACME Yoga"
}
}
}
}
],
"offset": 0,
"maxResults": 1,
"totalResults": 15
}
Name | Type | Description |
---|---|---|
id | string | The booking’s globally unique identifier (a GUID). |
bookingDateTime | string | The date and time when the API successfully created the booking; the booking’s creation timestamp (in UTC). See Dates and Times in Responses for more information. |
state | string | The booking’s current state. Possible Values:
|
sessionsDeducted | number | The number of sessions the booking will deduct from the associated pass. |
pass | object | Contains information about the pass that ispaying for the booking. |
pass.id | string | The pass’s globally unique identifier (a GUID). |
pass.type | string | The type of the pass. Possible Values:
|
pass.name | string | The pass’s name. |
class | object | Contains information about the class where the booking holds a space. |
class.id | number | The ID for this specific class within the current subscriber; the class’s ID. |
class.typeId | number | The ID for the class’s class type within the current subscriber. |
class.name | string | The name of the class. |
class.description | string | The class’ subscriber-configured description. This string contains HTML. |
class.registrationNotes | string | Special notes or instructions the subscriber wants to relay to users who are booking the class. For example, "Make sure you bring a sweat towel and bottle of water!" . |
class.classImageURLs | array of objects | Contains information about the different sizes of images available for the class. |
class.classImageURLs.size | string | The size of the image. Possible Values:
|
class.classImageURLs.url | string | The URL for the image. |
class.startDateTime | string | The date and time when the class starts (in UTC). See Dates and Times in Responses for more information. |
class.endDateTime | string | The date and time when the class ends (in UTC). See Dates and Times in Responses for more information. |
class.assistantNames | array of strings | Contains the names of all assistant teachers assigned to the class. |
class.roomName | string | The name of the room where the class is held (e.g., "Sun Room" or "Studio A" ). This value might be null if the subscriber hides their classes’ rooms. |
class.cancellationsAllowed | boolean | When true , indicates that the subscriber allows users to cancel bookings they make in this class, up to the cancellationWindowEndTime .When false , indicates that the subscriber does not allow users to cancel bookings they make in this class, regardless of the cancellationWindowEndTime . |
class.cancellationWindowEndTime | string | The date and time after which cancellations can no longer be made for bookings in the class (in the location’s time zone). |
class.serviceCategoryIds | array of numbers | The IDs of the service categories whose pricing options can pay for the class. |
class.staff | object | Contains information about the staff member who teaches the class. |
class.staff.id | number | The staff member’s ID within the current subscriber. |
class.staff.firstName | string | The staff member’s first name. This value might be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be the staff’s nickname if they have one configured. |
class.staff.lastName | string | The staff member’s last name. This value will be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be null if the staff member has a nickname configured. |
class.staff.gender | string | The staff member’s gender. Possible Values:
|
class.staff.staffImageURLs | array of objects | Contains information about the different sizes of images available for the staff member. |
class.staff.staffImageURLs.size | string | The size of the image. Possible Values:
|
class.staff.staffImageURLs.url | string | The URL for the image. |
class.staff.bio | string | The staff member’s biography. |
class.location | object | Contains information about the location where the class is taking place. |
class.location.id | number | The location’s globally unique ID. |
class.location.name | string | The location’s name. |
class.location.olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
class.location.subscriber | object | Contains information about the subscriber to whom the location belongs. |
class.location.subscriber.id | number | The subscriber’s globally unique ID. |
class.location.subscriber.name | string | The subscriber’s name. |
Errors
Example Error:
{
"error": {
"errorCode": "14000004",
"errorType": "invalidParameter",
"message": "The following parameter is invalid: locationId."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by ID)
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/bookings/{bookingId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}
This endpoint finds and returns the single booking associated with the passed ID.
Pagination
This endpoint does not support pagination.
Best Practices
- Use to pull booking details for a booking where you already have its ID.
- Use after making a POST Booking call to show the user their new booking.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
bookingId | string | Returns the single booking associated with this globally unique identifier (a GUID). This is the id property on the booking object returned from this call and the booking.id property returned from other calls in the API. |
Response
Partial example of response content structure:
{
"booking": {
"id": "f5405d87-46a0-4b48-a384-e26159e130d6",
"bookingDateTime": "2016-12-15T19:51:49.357Z",
...
}
...
}
This response object is the same as the objects contained in the items
field in the GET Bookings response . View that documentation for detailed information about the response object’s fields.
Errors
Example Error:
{
"error": {
"errorCode": "14040020",
"errorType": "bookingNotFound",
"message": "Booking not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
404 | 14040020 | bookingNotFound | The bookingId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
POST
curl -X POST \
-A "{yourAppName}" \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-H "Content-Type: application/json" \
-d '{
"locationId": 86784,
"classId": 5134512,
"bookingReconciliation":
{
"id": "153458",
"type": "PricingOption",
"pricingOptionTotal": 15.75
},
"suppressBookingConfirmationEmail": true,
"suppressPurchaseReceiptEmail": true,
"subscriberMarketingOptIn": false,
"userFirst": "Joseph",
"userLast": "Smith",
"userEmail": "[email protected]",
"userPhone": "8055555462",
"uniqueUserId": "aa4d78ad-5fde-40f4-bc15-a392b9643989",
"paymentDetails":
{
"creditCardNumber": "4012888888881881",
"creditCardExpirationYear": 2028,
"creditCardExpirationMonth": 1,
"billingName": "Joseph Smith",
"billingAddressLine1": "4051 Broad St",
"billingAddressLine2": "STE 201",
"billingCity": "San Luis Obispo",
"billingState": "CA",
"billingPostalCode": "93401"
}
}' \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/bookings"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/bookings");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
request.AddParameter("application/json", "{\n \"locationId\": 86784,\n \"classId\": 5134512,\n \"bookingReconciliation\":\n {\n \"id\": \"153458\",\n \"type\": \"PricingOption\",\n \"pricingOptionTotal\": 15.75\n },\n \"suppressBookingConfirmationEmail\": true,\n \"suppressPurchaseReceiptEmail\": true,\n \"subscriberMarketingOptIn\": false,\n \"userFirst\": \"Joseph\",\n \"userLast\": \"Smith\",\n \"userEmail\": \"[email protected]\",\n \"userPhone\": \"8055555462\",\n \"uniqueUserId\": \"aa4d78ad-5fde-40f4-bc15-a392b9643989\",\n \"paymentDetails\":\n {\n \"creditCardNumber\": \"4012888888881881\",\n \"creditCardExpirationYear\": 2028,\n \"creditCardExpirationMonth\": 1,\n \"billingName\": \"Joseph Smith\",\n \"billingAddressLine1\": \"4051 Broad St\",\n \"billingAddressLine2\": \"STE 201\",\n \"billingCity\": \"San Luis Obispo\",\n \"billingState\": \"CA\",\n \"billingPostalCode\": \"93401\"\n }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/bookings');
$request->setMethod(HTTP_METH_POST);
$request->setHeaders(array(
'content-type' => 'application/json',
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
$request->setBody('{
"locationId": 86784,
"classId": 5134512,
"bookingReconciliation":
{
"id": "153458",
"type": "PricingOption",
"pricingOptionTotal": 15.75
},
"suppressBookingConfirmationEmail": true,
"suppressPurchaseReceiptEmail": true,
"subscriberMarketingOptIn": false,
"userFirst": "Joseph",
"userLast": "Smith",
"userEmail": "[email protected]",
"userPhone": "8055555462",
"uniqueUserId": "aa4d78ad-5fde-40f4-bc15-a392b9643989",
"paymentDetails":
{
"creditCardNumber": "4012888888881881",
"creditCardExpirationYear": 2028,
"creditCardExpirationMonth": 1,
"billingName": "Joseph Smith",
"billingAddressLine1": "4051 Broad St",
"billingAddressLine2": "STE 201",
"billingCity": "San Luis Obispo",
"billingState": "CA",
"billingPostalCode": "93401"
}
}');
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
payload = "{\n \"locationId\": 86784,\n \"classId\": 5134512,\n \"bookingReconciliation\":\n {\n \"id\": \"153458\",\n \"type\": \"PricingOption\",\n \"pricingOptionTotal\": 15.75\n },\n \"suppressBookingConfirmationEmail\": true,\n \"suppressPurchaseReceiptEmail\": true,\n \"subscriberMarketingOptIn\": false,\n \"userFirst\": \"Joseph\",\n \"userLast\": \"Smith\",\n \"userEmail\": \"[email protected]\",\n \"userPhone\": \"8055555462\",\n \"uniqueUserId\": \"aa4d78ad-5fde-40f4-bc15-a392b9643989\",\n \"paymentDetails\":\n {\n \"creditCardNumber\": \"4012888888881881\",\n \"creditCardExpirationYear\": 2028,\n \"creditCardExpirationMonth\": 1,\n \"billingName\": \"Joseph Smith\",\n \"billingAddressLine1\": \"4051 Broad St\",\n \"billingAddressLine2\": \"STE 201\",\n \"billingCity\": \"San Luis Obispo\",\n \"billingState\": \"CA\",\n \"billingPostalCode\": \"93401\"\n }\n}"
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}",
'content-type': "application/json"
}
conn.request("POST", "/affiliate/api/v1/bookings", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/bookings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
request["content-type"] = 'application/json'
request.body = "{\n \"locationId\": 86784,\n \"classId\": 5134512,\n \"bookingReconciliation\":\n {\n \"id\": \"153458\",\n \"type\": \"PricingOption\",\n \"pricingOptionTotal\": 15.75\n },\n \"suppressBookingConfirmationEmail\": true,\n \"suppressPurchaseReceiptEmail\": true,\n \"subscriberMarketingOptIn\": false,\n \"userFirst\": \"Joseph\",\n \"userLast\": \"Smith\",\n \"userEmail\": \"[email protected]\",\n \"userPhone\": \"8055555462\",\n \"uniqueUserId\": \"aa4d78ad-5fde-40f4-bc15-a392b9643989\",\n \"paymentDetails\":\n {\n \"creditCardNumber\": \"4012888888881881\",\n \"creditCardExpirationYear\": 2028,\n \"creditCardExpirationMonth\": 1,\n \"billingName\": \"Joseph Smith\",\n \"billingAddressLine1\": \"4051 Broad St\",\n \"billingAddressLine2\": \"STE 201\",\n \"billingCity\": \"San Luis Obispo\",\n \"billingState\": \"CA\",\n \"billingPostalCode\": \"93401\"\n }\n}"
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/bookings
This endpoint allows users to book classes.
Retrying Failed Requests
This endpoint supports idempotent requests, meaning that you can safely retry a request without creating a duplicate booking. Idempotent requests create a single booking, no matter how many times you send the request within a 24 hour period. If a booking was successfully created by a previous request using the same idempotency key, you will receive a 200 OK
instead of a 201 Created
. Idempotent requests are especially useful when dealing with connection time outs and HTTP 500 errors.
If a request fails with an HTTP 400 error, please correct your request and use a new idempotency key, then make your request again. If the same idempotency key is used within a 24 hour time period, you will receive the same cached response that you received the first time; in this case, a 400 error.
Pass a GUID as an Idempotency-Key header to make an idempotent request. Most programming languages come with functions that can create GUID strings for you. For example:
Language | Function |
---|---|
C# | Guid.NewGuid() |
PHP | uniqueid |
Python | uuid |
Ruby | SecureRandom.uuid |
Pagination
This endpoint does not support pagination.
Best Practices
- Use once a user has selected a class and pricing option they want to purchase.
- Use once a user has selected a class and a preexisting pass they want to use to book the class.
- Use after storing the
subscriber.creditCardTypesAccepted
array returned from GET Locations. If a user tries to make a booking with a pricing option and an unacceptable card type, the call will fail. - Use before calling POST LiabilityWaivers so you have a
bookingId
with which to make that call.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
Content-Type | string | Defines the format of the request so the API can correctly process it. application/json is the only accepted value at this time. |
Idempotency-Key Optional |
Guid | A GUID used as the idempotency key for this booking request. This key expires after 24 hours.max length: 36, min length: 36 |
Request Body
{
"locationId": 86784,
"classId": 5134512,
"bookingReconciliation":
{
"id": "153458",
"type": "PricingOption",
"pricingOptionTotal": 15.75
},
"suppressBookingConfirmationEmail": true,
"suppressPurchaseReceiptEmail": true,
"subscriberMarketingOptIn": false,
"userFirst": "Joseph",
"userLast": "Smith",
"userEmail": "[email protected]",
"userPhone": "8055555462",
"uniqueUserId": "aa4d78ad-5fde-40f4-bc15-a392b9643989",
"paymentDetails":
{
"creditCardNumber": "4012888888881881",
"creditCardExpirationYear": 2028,
"creditCardExpirationMonth": 1,
"creditCardCVV": "0123",
"billingName": "Joseph Smith",
"billingAddressLine1": "4051 Broad St",
"billingAddressLine2": "STE 201",
"billingCity": "San Luis Obispo",
"billingState": "CA",
"billingPostalCode": "93401"
}
}
Name | Type | Description |
---|---|---|
locationId | number | The globally unique ID of the location where the booking is taking place. This is the id property on the location object returned from GET Locations and the location.id property returned from other calls in the API. |
classId | number | The ID of the class where the booking is reserving a space. This is the id property on the class object returned from GET Classes and the class.id property returned from other calls in the API. |
bookingReconciliation | object | Specifies whether a pass or a pricing option is paying for the class. |
bookingReconciliation.id | string | Will be the pass’s id (a GUID) if using a pass to reconcile the booking.Will be the pricing option’s id if using a pricing option to reconcile the booking. |
bookingReconciliation.type | string | Specifies whether the user is using a pass or pricing option to pay for the booking. Accepted Values:
|
bookingReconciliation.pricingOptionTotal Optional: You must provide this value when bookingReconciliation.type is "PricingOption" |
number | The expected cost of the pricing option the user is about to purchase. This ensures that the subscriber has not changed the price in the time between selecting and purchasing the pricing option. Pass null for this value when bookingReconciliation.type is "Pass" . |
suppressBookingConfirmationEmail Optional |
boolean | When true , the subscriber will not send their customized booking confirmation email to the user. Instead, you can send a tailored email that is consistent with the user’s experience within your app.When false or omitted, the subscriber will send their booking confirmation email to the user. |
suppressPurchaseReceiptEmail Optional |
boolean | When true , the subscriber will not send the purchase receipt email to the user. Instead, you can send a tailored email that is consistent with the user’s experience within your app.When false or omitted, the subscriber will send the purchase receipt email to the user. |
subscriberMarketingOptIn Optional |
boolean | When true , the user’s email address is added to the subscriber’s marketing email list.When false or omitted, the user’s email is not added to the subscriber’s marketing email list. |
userFirst Optional: You must provide this value when bookingReconciliation.type is "PricingOption" |
string | The user’s first name.max length: 100 | min length: 1 |
userLast Optional: You must provide this value when bookingReconciliation.type is "PricingOption" |
string | The user’s last name.max length: 100 | min length: 1 |
userEmail Optional: You must provide this value when bookingReconciliation.type is "PricingOption" |
string | The user’s email address.max length: 255 | min length: 1 |
userPhone Optional |
string | The user’s phone number.max: 20 |
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
paymentDetails Optional: Set this value to null when bookingReconciliation.type is "Pass" . |
object | When bookingReconciliation.type is "PricingOption" , this object must contain the user’s credit card and billing information to pay for the booking. |
paymentDetails.creditCardNumber | string | The full credit card number being charged for the pricing option.max length: 16 | min length: 15 |
paymentDetails.creditCardExpirationYear | number | The 4-digit year when the credit card expires.max: 2100 | min: 2000 |
paymentDetails.creditCardExpirationMonth | number | The digit representing the month when the credit card expires. (E.g., 1 indicates January, 10 indicates October.)max: 12 | min: 1 |
paymentDetails.creditCardCvv Optional |
string | The credit card’s 3 or 4 digit CVV codemax length: 4 | min length: 3 |
paymentDetails.billingName | string | The billing name on the credit card.max: 200 | min: 1 |
paymentDetails.billingAddressLine1 | string | The street portion of the billing address.max length: 255 | min length: 1 |
paymentDetails.billingAddressLine2 | string | Additional address information (e.g., the apartment number, suite number, floor number, etc.).max length: 255 |
paymentDetails.billingCity | string | The city portion of the billing address.max length: 50 | min length: 1 |
paymentDetails.billingState | string | The state code portion of the billing address (e.g. For California in the USA, "CA" .).max length: 10 | min length: 1 |
paymentDetails.billingPostalCode | string | The postal code portion of the billing address.max length: 15 | min length: 1 |
Response
HTTP Status Code: 200 OK
The API returns this code and the first request’s response body when you make subsequent requests – using the sameIdempotency-Key
header value – to this endpoint. A 200 is only returned if the original request resulted in a 201.HTTP Status Code: 201 Created
{
"booking": {
"id": "d2b68b2f-35ca-4eeb-b8ab-babd65058b35",
"bookingDateTime": "2016-12-16T09:54:41.137",
"sessionsDeducted": 1
},
"pass": {
"id": "d1e9b2be-655a-4419-b7dd-30aa84f7aa70",
"type": "DropIn",
"name": "Single Yoga Class",
"totalSessions": 1,
"sessionsRemaining": 0,
"activationType": "OnPurchaseDate",
"activationDateTime": "2016-12-15T00:00:00",
"expirationDateTime": "2017-12-15T00:00:00"
},
"location": {
"id": 12856,
"name": "ACME Yoga",
"olsonTimeZone": "America/Los_Angeles",
"contactInfo": {
"phone": "8055551234",
"streetAddress": "4051 Broad St",
"city": "San Luis Obispo",
"stateCode": "CA",
"postalCode": "93405",
"countryCode": "US",
"latitude": 35.300495,
"longitude": -120.657846
},
"subscriber": {
"id": 13548,
"name": "ACME Yoga",
"website": "https://yogashala.com",
"cancellationPolicy": null,
"refundPolicy": null
}
},
"class": {
"id": 31034,
"typeId": 7,
"name": "Beginning Hatha Yoga",
"description": "A gentle introduction to the Hatha practice.",
"registrationNotes": "Bring a yoga mat and a large bottle of water.",
"startDateTime": "2016-12-15T17:00:00",
"endDateTime": "2017-12-15T17:00:00",
"assistantNames": [],
"roomName": null,
"cancellationsAllowed": true,
"cancellationWindowEndTime": "2016-12-15T17:00:00",
"serviceCategoryIds": [
25
],
"staff": {
"id": 3,
"firstName": "Thomas",
"lastName": "Jones",
"gender": "Male",
"bio": null,
"staffImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/3_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/3_large.jpg?v=23"
},
{
"size": "Mobile",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/3_mobile.jpg?v=23"
}
]
},
"classImageURLs": [
{
"size": "XLarge",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_xLarge.jpg?v=23"
},
{
"size": "Large",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_large.jpg?v=23"
},
{
"size": "Unscaled",
"url": "https://clients.mindbodyonline.com
/studios/ACMEYoga/reservations/7_.jpg?v=23"
}
]
},
"purchase": {
"id": "6a5682e5-fa55-4db8-b739-b2d942f74177",
"transactionId": 71300,
"purchaseDateTime": "2016-12-15T19:32:26.867Z",
"pricingOption": {
"id": 5176,
"type": "DropIn",
"name": "Single Yoga Class",
"description": ,
"subtotal": 15,
"tax": 0.75,
"total": 15.75,
"currencyCode": "USD",
"userRestrictions": [
"None"
]
}
}
}
Name | Type | Description |
---|---|---|
booking | object | Contains information about the booking created by the request. |
booking.id | string | The booking’s globally unique identifier (a GUID). |
booking.bookingDateTime | string | The date and time when the API successfully created the booking; the booking’s creation timestamp (in UTC). See Dates and Times in Responses for more information. |
booking.sessionsDeducted | number | The number of sessions the booking will deduct from the associated pass. |
pass | object | Contains information about the pass that ispaying for the booking. |
pass.id | string | The pass’s globally unique identifier (a GUID). |
pass.type | string | The type of the pass. Possible Values:
|
pass.name | string | The pass’s name. |
pass.totalSessions | number | The number of sessions attached to the pass at the time of purchase. If the pass’s type is "Unlimited" , you can ignore this field. |
pass.sessionsRemaining | number | The number of unused sessions on the pass. If the pass’s type is "Unlimited" , you can ignore this field. |
pass.activationType | string | Specifies the pass’s activation type. Possible Values:
|
pass.activationDateTime | string | The date and time after which the pass reconciles bookings (in UTC). See Dates and Times in Responses for more information. This value may be null . Read this note for more information. |
pass.expirationDateTime | string | The date and time after which the pass no longer reconciles bookings (in UTC). See Dates and Times in Responses for more information. This value may be null . Read this note for more information. |
location | object | Contains information about the location where the booking is taking place. |
location.id | number | The location’s globally unique ID. |
location.name | string | The location’s name. |
location.olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
location.contactInfo | object | Contains contact information for the location. |
location.contactInfo.phone | string | The location’s phone number. |
location.contactInfo.streetAddress | string | The street address portion of the location’s address. |
location.contactInfo.city | string | The city portion of the location’s address. |
location.contactInfo.stateCode | string | The state code portion of the location’s address (e.g. "CA" for California in the USA.). |
location.contactInfo.postalCode | string | The postal code portion of the location’s address. |
location.contactInfo.countryCode | string | The location’s country (e.g., "US" ). This value will always be an ISO ALPHA-2 Code. |
location.contactInfo.latitude | number | The location’s latitude. |
location.contactInfo.longitude | number | The location’s longitude. |
location.subscriber | object | Contains information about the subscriber to whom the location belongs. |
location.subscriber.id | number | The subscriber’s globally unique ID. |
location.subscriber.name | string | The subscriber’s name. |
location.subscriber.website | string | The URL for the subscriber’s main website. |
location.subscriber.cancellationPolicy | string | The subscriber’s cancellation policy text. |
location.subscriber.refundPolicy | string | The subscriber’s refund policy text. |
class | object | Contains information about the class where the booking holds a space. |
class.id | number | The ID for this specific class within the current subscriber; the class’s ID. |
class.typeId | number | The ID for the class’s class type within the current subscriber. |
class.name | string | The name of the class. |
class.description | string | The class’ subscriber-configured description. This string contains HTML. |
class.registrationNotes | string | Special notes or instructions the subscriber wants to relay to users who are booking the class. For example, "Make sure you bring a sweat towel and bottle of water!" . |
class.startDateTime | string | The date and time when the class starts (in UTC). See Dates and Times in Responses for more information. |
class.endDateTime | string | The date and time when the class ends (in UTC). See Dates and Times in Responses for more information. |
class.assistantNames | array of strings | Contains the names of all assistant teachers assigned to the class. |
class.roomName | string | The name of the room where the class is held (e.g., "Sun Room" or "Studio A" ). This value might be null if the subscriber hides their classes’ rooms. |
class.cancellationsAllowed | boolean | When true , indicates that the subscriber allows users to cancel bookings they make in this class, up to the cancellationWindowEndTime .When false , indicates that the subscriber does not allow users to cancel bookings they make in this class, regardless of the cancellationWindowEndTime . |
class.cancellationWindowEndTime | string | The date and time after which cancellations can no longer be made for bookings in the class (in UTC). See Dates and Times in Responses for more information. |
class.serviceCategoryIds | array of numbers | The IDs of the service categories whose pricing options can pay for the class. |
class.staff | object | Contains information about the staff member who teaches the class. |
class.staff.id | number | The staff member’s ID within the current subscriber. |
class.staff.firstName | string | The staff member’s first name. This value might be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be the staff’s nickname if they have one configured. |
class.staff.lastName | string | The staff member’s last name. This value will be null if the subscriber has hidden staff names.If the subscriber uses staff nicknames, this value will be null if the staff member has a nickname configured. |
class.staff.gender | string | The staff member’s gender. Possible Values:
|
class.staff.bio | string | The staff member’s biography. |
class.staff.staffImageURLs | array of objects | Contains information about the different sizes of images available for the staff member. |
class.staff.staffImageURLs.size | string | The size of the image. Possible Values:
|
class.staff.staffImageURLs.url | string | The URL for the image. |
class.classImageURLs | array of objects | Contains information about the different sizes of images available for the class. |
class.classImageURLs.size | string | The size of the image. Possible Values:
|
class.classImageURLs.url | string | The URL for the image. |
purchase | object | Contains information about the purchase that the booking created. This object will be null if a pass is paying for the booking. |
purchase.id | string | The purchase’s globally unique identifier. |
purchase.transactionId | number | The purchase’s transaction ID, unique within the booking’s subscriber. Subscribers refer to this as the “sale ID” and might need this number to look up a purchase in their data. |
purchase.purchaseDateTime | string | The date and time when the API successfully created the purchase; the purchase’s creation timestamp (in UTC). See Dates and Times in Responses for more information. |
purchase.pricingOption | array of objects | Contains information about the purchased pricing option. |
purchase.pricingOption.id | number | The pricing option’s ID at the current subscriber. |
purchase.pricingOption.type | string | Describes the type of the pricing option. Possible Values:
|
purchase.pricingOption.name | string | The pricing option’s name. |
purchase.pricingOption.description | string | The pricing option’s subscriber-configured description. |
purchase.pricingOption.subtotal | number | The total cost of the pricing option before applying taxes. |
purchase.pricingOption.tax | number | The total cost of taxes for the pricing option. |
purchase.pricingOption.total | number | The total cost of the pricing option, including taxes. |
purchase.pricingOption.currencyCode | string | A currency code based on the ISO 4217 specification (e.g., "USD" represents the US dollar). |
purchase.pricingOption.userRestrictions | array of strings | Specifies whether or not the subscriber restricts the purchasing of this pricing option to users that meet specific criteria. Possible Values:
|
Errors
Example Error:
{
"error": {
"errorCode": "14040007",
"errorType": "pricingOptionNotFound",
"message": "Pricing option not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000003 | missingRequiredProperty | Returned when one of the required request properties is null or empty. Check the error’s message property to find the name of the invalid property. |
400 | 14000005 | invalidValue | Returned when a request body property:
message property to find the name of the invalid property. |
400 | 14000007 | invalidFieldCombination | Returned when you use two incompatible request body fields together (e.g., passing in bookingReconciliation.pricingOptionTotal when bookingReconciliation.type is "Pass" ). |
400 | 14000020 | reconciliationPOClassMismatch | The pricing option specified in the request does not pay for the specified class. |
400 | 14000021 | reconciliationPassClassMismatch | The pass specified in the request does not pay for the specified class. |
400 | 14000022 | reconciliationNotEnoughSessions | The pass specified in the request does not have enough sessions remaining to pay for the class. |
400 | 14000023 | reconciliationCanNotBeCompletedByUser | The user cannot purchase the pricing option due to its userRestrictions . The user should contact the subscriber for more information. |
400 | 14000024 | reconciliationPOPriceMismatch | Returned when the bookingReconciliation.pricingOptionTotal does not match the actual price of the pricing option. |
400 | 14000030 | classNotCurrentlyAvailableForBooking | The class cannot be booked at this time. |
400 | 14000031 | classOutsideBookingWindow | The user cannot book the class because the current time is outside its booking window. |
400 | 14000032 | classNoAvailableCapacity | The user cannot book the class because it is full. |
400 | 14000033 | classCancelled | The subscriber cancelled the class; users cannot book it. |
400 | 14000039 | classNotBookableByUser | The user cannot book the class. They should contact the subscriber for more information. |
400 | 14000080 | creditCardTypeNotAccepted | The subscriber does not accept the card type specified in the request. If you receive this error, alter your workflow so that you store the creditCardTypesAccepted property returned from GET Locations and use it to validate the card type being sent in this request. |
400 | 14000081 | creditCardExpired | The user cannot user their credit card because it is expired. |
400 | 14000082 | creditCardDeclinedByProcessor | The subscriber’s payment processor declined the request’s credit card. The user should contact the subscriber to troubleshoot this issue further. |
400 | 14000083 | creditCardProcessingTimeout | The credit card processor took too long and the call timed out. The user should contact the subscriber to troubleshoot this issue further. |
400 | 14000089 | creditCardProcessingFailure | The credit card processor failed to charge the user’s card. They should contact the subscriber to troubleshoot this issue further. |
400 | 14040001 | locationNotFound | The locationId passed in the request body was not found. |
400 | 14040005 | classNotFound | The classId passed in the request body was not found. |
400 | 14040007 | pricingOptionNotFound | The pricing option associated with the bookingReconciliation.id passed in the request body was not found. |
400 | 14040030 | passNotFound | The pass associated with the bookingReconciliation.id was either not found, or it had no remaining sessions. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
409 | 14090020 | bookingAlreadyInProgress | A previous request with the same Idempotency-Key header is still processing. The API will not complete this request. |
415 | 14150002 | unsupportedMediaType | A Content-Type header was passed with a value other than application/json . This is the only accepted content type for this endpoint. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
500 | 15009999 | criticalServerError | The user’s booking at the subscriber succeeded and their card was charged (if booking with a pricing option), but something prevented us from tracking this information against your Affiliate account. Please move your integration out of a live environment and contact Mindbody developer support immediately. |
DELETE
curl -X DELETE \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}");
var request = new RestRequest(Method.DELETE);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}');
$request->setMethod(HTTP_METH_DELETE);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("DELETE", "/api/v1/users/{uniqueUserId}/bookings/{bookingId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Delete.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/bookings/{bookingId}
This endpoint allows users to cancel a booking.
Pagination
This endpoint does not support pagination.
Best Practices
- Use when a user wants to cancel a booking and remove it from their schedule.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
bookingId | string | The globally unique identifier of the booking your user wants to cancel (a GUID). This is the id property on the booking object return from GET Bookings and the booking.id property on the object returned from POST Booking. |
Query Parameters
Name | Type | Description |
---|---|---|
suppressCancellationConfirmationEmail Optional |
boolean | When true , the subscriber will not send their customized cancellation confirmation email to the user. Instead, you can send a tailored email that is consistent with the user’s experience within your app.when false or omitted, the subscriber will send their customized cancellation confirmation email to the user. |
Response
HTTP Status Code: 200 OK
{
"message": "Cancellation successful.",
"pass": {
"id": "d1e9b2be-655a-4419-b7dd-30aa84f7aa70"
}
}
Name | Type | Description |
---|---|---|
message | string | A brief message describing the cancellation’s status. Possible Values:
|
pass | object | Contains information about the pass that reclaimed a session after the user cancelled this booking. |
pass.id | string | The globally unique identifier of the pass that reclaimed a session. |
Errors
Example Error:
{
"error": {
"errorCode": "14090013",
"errorType": "bookingAlreadyCancelled",
"message": "Booking cancellation failed. Booking already cancelled."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
404 | 14040020 | bookingNotFound | The bookingId passed as a URL Parameter was not found. |
409 | 14090011 | bookingNotCancellable | The user cannot cancel the booking at this time. |
409 | 14090012 | bookingCancellationOutsideTimeWindow | The current time is outside the subscriber’s configured cancellation window. |
409 | 14090013 | bookingAlreadyCancelled | The booking has already been cancelled. |
409 | 14090014 | bookingNotCancellableClassCancelled | The subscriber cancelled the booking’s class; the booking cannot be cancelled. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
Passes
Passes are purchased pricing options on a user’s account that they can use to book classes.
Activation and Expiration Dates
If a user cancels all bookings associated with a pass, and its activationType
is OnFirstVisitScheduledWithPass
, both its activationDateTime
and expirationDateTime
will be null
. These values will not be populated until the user uses the pass to reconcile at least one booking. A pass in this situation can be used at any point in the future, and will not expire until it is used to reconcile a booking.
GET
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/passes", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes
This endpoint retrieves passes on a user’s account.
You can retrieve a specific pass by calling GET (by ID).
Pagination
The endpoint supports pagination.
Best Practices
- Make this call at the start of a workflow that does not support “guest” bookings so you have context for what the user already has on their account. The pass information can then be used to:
- Indicate classes that a user’s pass(es) may pay for
- Allow users to select a pass, then find bookable classes that the pass will pay for
- Use before booking to allow users to choose a pass on file instead of purchasing a new pricing option.
- Use before making a POST Booking call if the user is a not a “guest” user.
- Use when constructing account status pages to show a user a list of their current and/or expired passes.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
Query Parameters
Name | Type | Description |
---|---|---|
subscriberId Optional |
number | Filters results down to the user’s passes at the subscriber identified by this ID. This is the subscriber.id property on the location object returned from multiple calls in the API. |
limitToUsable Optional |
boolean | When true or omitted, filters results down to passes that have remaining sessions and have not yet expired.When false , returns all passes regardless of their remaining session count or expiration date.default: true |
maxResults Optional |
number | Sets the maximum number of records returned in the results.default: 10 | max: 100 | min: 0 |
offset Optional |
number | Sets the number of records skipped over to reach the returned results.default: 0 | min: 0 |
orderBy Optional |
string | Designates which field in the response body orders the results. Accepted Values:
|
order Optional |
string | Orders the results in ascending or descending order based on the field specified by orderBy .Accepted Values:
|
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": "598a6916-7876-406e-9537-db6af825f9a2",
"pricingOptionId": 5176,
"purchaseId": "6b93a69e-4547-412d-a00e-700bd3691bd4",
"subscriber": {
"id": 135415,
"name": "ACME Yoga"
},
"type": "Series",
"name": "5 Pack Yoga Classes",
"totalSessions": 5,
"sessionsRemaining": 4,
"activationType": "OnPurchaseDate",
"activationDateTime": "2016-12-15T00:00:00",
"expirationDateTime": "2017-12-15T00:00:00",
"serviceCategoryId": 25,
"usableState": "Usable"
}
],
"offset": 0,
"maxResults": 1,
"totalResults": 7
}
Name | Type | Description |
---|---|---|
id | string | The pass’s globally unique identifier (a GUID). |
pricingOptionId | number | The ID of the pricing option that generated this pass when purchased. |
purchaseId | string | The globally unique identifier of the purchase that created the pass. This is the id property returned from GET Purchases. |
subscriber | object | Contains information about the subscriber where the user purchased the pass. |
subscriber.id | number | The subscriber’s globally unique ID. |
subscriber.name | string | The subscriber’s name. |
type | string | The type of the pass. Possible Values:
|
name | string | The pass’s name. |
totalSessions | number | The number of sessions attached to the pass at the time of purchase. If the pass’s type is "Unlimited" , you can ignore this field. |
sessionsRemaining | number | The number of unused sessions on the pass. If the pass’s type is "Unlimited" , you can ignore this field. |
activationType | string | Specifies the pricing option’s activation type. Possible Values:
|
activationDateTime | string | The date and time after which the pass reconciles bookings (in UTC). See Dates and Times in Responses for more information. This value may be null . Read this note for more information. |
expirationDateTime | string | The date and time after which the pass no longer reconciles bookings (in UTC). See Dates and Times in Responses for more information. This value may be null . Read this note for more information. |
serviceCategoryId | number | The ID of the service category at the current subscriber to which the pass belongs. |
usableState | string | Specifies whether or not the user can use the pass. Possible Values:
|
Errors
Example Error:
{
"error": {
"errorCode": "14000004",
"errorType": "invalidParameter",
"message": "The following parameter is invalid: limitToUsable."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by ID)
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes/{passId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes/{passId}");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes/{passId}');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/passes/{passId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes/{passId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/passes/{passId}
This endpoint finds and returns the single pass associated with the passed ID.
Pagination
This endpoint does not support pagination.
Best Practices
- Use when fetching pass details for a pass where you already have its ID.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
passId | string | Returns the single pass associated with this globally unique identifier (a GUID). Do not use query parameters when fetching this resource. |
Response
Partial example of response content structure:
{
"id": "598a6916-7876-406e-9537-db6af825f9a2",
"purchaseId": "6b93a69e-4547-412d-a00e-700bd3691bd4",
...
}
This response object is the same as the objects contained in the items
field in the GET Passes response . View that documentation for detailed information about the response object’s fields.
Errors
Example Error:
{
"error": {
"errorCode": "14040030",
"errorType": "passNotFound",
"message": "Pass not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
404 | 14040030 | passNotFound | The passId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
Purchases
Purchases
Any call to POST Booking using a bookingReconciliation.type
of PricingOption
generates a purchase record. Purchases contain information about:
- the pricing option purchased
- the pass created as a result of the purchase
- the location where the user used the pass
Purchases are essentially receipts; they represent a snapshot of a purchase at a specific point in time. Their information does not change as subscribers make alterations to their data. The only field that may change is the purchase’s purchaseState
.
Returns and Refunds
If a user wants to return or receive a refund for a pass, they must contact the subscriber and work it out with the business. Currently, no APIs exist to accommodate return or refund workflows.
Use the GET Locations call to retrieve a subscriber’s refund policy text.
GET
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/purchases", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases
This endpoint retrieves purchases on a user’s account.
You can retrieve a specific purchase by calling GET (by ID).
Pagination
This endpoint supports pagination.
Best Practices
- Use when constructing account status pages to show the user a list of their purchases.
- Use when you need to find the location where a user purchased a pass. This is useful when:
- Showing a pass’s expiration date in the proper time zone context
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
Query Parameters
Name | Type | Description |
---|---|---|
locationId Optional |
number | Filters the results down to the user’s purchases at the location identified by this ID. This is the id property on the location object returned from the GET Locations call and the location.id property returned from other calls in the API. |
subscriberId Optional |
number | Filters results down to the user’s purchases at the subscriber identified by this ID. This is the subscriber.id property on the location object returned from multiple calls in the API. |
fromPurchaseDateTime Optional |
string | The UTC date/time that sets the beginning of the time-frame within which you are searching for purchases. The results contain all purchases made on and after this date/time up through the specified toPurchaseDateTime . If toPurchaseDateTime is omitted, purchases are returned up to the current time.See Dates and Times in Requests for more information. |
toPurchaseDateTime Optional |
string | The UTC date/time that sets the end of the time-frame within which you are searching for purchases. The results will contain all purchases made on and before this date/time back through the specified fromPurchaseDateTime . If fromPurchaseDateTime is omitted, purchases are returned up to 365 days in the past.See Dates and Times in Requests for more information. |
maxResults Optional |
number | Sets the maximum number of records returned in the results.default: 50 | max: 500 | min: 0 |
offset Optional |
number | Sets the number of records skipped over to reach the returned results.default: 0 | min: 0 |
orderBy Optional |
string | Designates which field in the response body orders the results. Accepted Values:
|
order Optional |
string | Orders the results in ascending or descending order based on the field specified by orderBy .Accepted Values:
|
Response
HTTP Status Code: 200 OK
{
"items": [
{
"id": "6b93a69e-4547-412d-a00e-700b91691bd4",
"passId": "598a6916-7876-406e-9537-db6e4825f9a2",
"transactionId": 71300,
"purchaseState": "Purchased",
"pricingOption": {
"id": 5176,
"serviceCategoryId": 25,
"name": "Single Yoga Class",
"description": null,
"type": "DropIn",
"subtotal": 15,
"tax": 0.75,
"total": 15.75,
"currencyCode": "USD",
"activationType": "OnPurchaseDate",
"expirationTimeUnit": "Months",
"expirationTimeUnitValue": 12,
"activationDateTime": "2017-01-15T00:00:00",
"expirationDateTime": "2018-01-15T00:00:00",
"userRestrictions": [
"None"
]
},
"location": {
"id": 12856,
"name": "ACME Yoga",
"olsonTimeZone": "America/Los_Angeles",
"subscriber": {
"id": 13548,
"name": "ACME Yoga",
"website": "https://yogashala.com",
"cancellationPolicy": null,
"refundPolicy": null
},
"contactInfo": {
"phone": "8055551234",
"streetAddress": "4051 Broad St",
"city": "San Luis Obispo",
"stateCode": "CA",
"postalCode": "93405",
"countryCode": "US",
"longitude": -120.657846,
"latitude": 35.300495
}
},
"purchaseDateTime": "2016-12-15T19:32:26.867Z"
}
],
"offset": 0,
"maxResults": 1,
"totalResults": 20
}
Name | Type | Description |
---|---|---|
id | string | The purchase’s globally unique identifier. |
passId | string | The globally unique identifier of the pass that the purchase created. This is the id property on the pass object returned by GET Passes and the pass.id property returned from other calls in the API. |
transactionId | number | The purchase’s transaction ID, unique within the booking’s subscriber. Subscribers refer to this as the “sale ID” and might need this number to look up a purchase in their data. |
purchaseState | string | The purchase’s current state. Possible Values:
|
pricingOption | object | Contains information about the purchased pricing option. |
pricingOption.id | number | The pricing option’s ID at the current subscriber. |
pricingOption.serviceCategoryId | number | The ID of the service category at the current subscriber to which the pricing option belongs. |
pricingOption.name | string | The pricing option’s name. |
pricingOption.description | string | The pricing option’s subscriber-configured description. |
pricingOption.type | string | Describes the type of the pricing option. Possible Values:
|
pricingOption.subtotal | number | The total cost of the pricing option before applying taxes. |
pricingOption.tax | number | The total cost of taxes for the pricing option. |
pricingOption.total | number | The total cost of the pricing option, including taxes. |
pricingOption.currencyCode | string | A currency code based on the ISO 4217 specification (e.g., "USD" represents the US dollar). |
pricingOption.activationType | string | Specifies the pricing option’s activation type. Possible Values:
|
pricingOption.expirationTimeUnit | string | The type of unit used to calculate the pricing option’s expiration date (e.g., this is the “months” in a pricing option that isactive for “12 months”). Possible Values:
expirationTimeUnitValue . |
pricingOption.expirationTimeUnitValue | number | The number of expirationUnits used to calculate the pricing option’s expiration date (e.g., this is the “12” in a pricing option that isactive for “12 months”). This is always used with expirationTimeUnit . |
pricingOption.activationDateTime | string | The date and time after which the pricing option reconciles bookings (in UTC). See Dates and Times in Responses for more information. |
pricingOption.expirationDateTime | string | The date and time after which the pricing option no longer reconciles bookings (in UTC). See Dates and Times in Responses for more information. |
pricingOption.userRestrictions | array of strings | Specifies whether or not the subscriber restricts the purchasing of this pricing option to users that meet specific criteria. Possible Values:
|
location | object | Contains information about the location where the user made this purchase. |
location.id | number | The location’s globally unique ID. |
location.name | string | The location’s name. |
location.olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
location.subscriber | object | Contains information about the subscriber to whom the location belongs. |
location.subscriber.id | number | The subscriber’s globally unique ID. |
location.subscriber.name | string | The subscriber’s name. |
location.subscriber.website | string | The URL for the subscriber’s main website. |
location.subscriber.cancellationPolicy | string | The subscriber’s cancellation policy text. |
location.subscriber.refundPolicy | string | The subscriber’s refund policy text. |
location.contactInfo | object | Contains contact information for the location. |
location.contactInfo.phone | string | The location’s phone number. |
location.contactInfo.streetAddress | string | The street address portion of the location’s address. |
location.contactInfo.city | string | The city portion of the location’s address. |
location.contactInfo.stateCode | string | The state code portion of the location’s address (e.g. "CA" for California in the USA.). |
location.contactInfo.postalCode | string | The postal code portion of the location’s address. |
location.contactInfo.countryCode | string | The location’s country (e.g., "US" ). This value will always be an ISO ALPHA-2 Code. |
location.contactInfo.longitude | number | The location’s longitude. |
location.contactInfo.latitude | number | The location’s latitude. |
purchaseDateTime | string | The date and time when the API successfully created the purchase; the purchase’s creation timestamp (in UTC). See Dates and Times in Responses for more information. |
Errors
Example Error:
{
"error": {
"errorCode": "14000004",
"errorType": "invalidParameter",
"message": "The following parameter is invalid: purchaseDateTime."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000004 | invalidParameter | Returned when a query parameter:
message property to find the name of the invalid query parameter. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
GET (by ID)
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases/{purchaseId}"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases/{purchaseId}");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases/{purchaseId}');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/users/{uniqueUserId}/purchases/{purchaseId}", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases/{purchaseId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/users/{uniqueUserId}/purchases/{purchaseId}
This endpoint finds and returns the single purchase associated with the passed ID.
Pagination
This endpoint does not support pagination.
Best Practices
- Use when you want to get purchase details when you already have the purchase’s ID.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
uniqueUserId | string | The user’s unique identifier within your system. This ID must:
|
purchaseId | string | Returns the single purchase associated with this globally unique identifier (a GUID). Do not use query parameters when fetching this resource. |
Response
Partial example of response content structure:
{
"id": "6b93a69e-4547-412d-a00e-700b91691bd4",
"passId": "598a6916-7876-406e-9537-db6e4825f9a2",
...
}
This response object is the same as the objects contained in the items
field in the GET Purchases response . View that documentation for detailed information about the response object’s fields.
Errors
Example Error:
{
"error": {
"errorCode": "14040040",
"errorType": "purchaseNotFound",
"message": "Purchase not found."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040010 | userNotFound | The uniqueUserId passed as a URL Parameter was not found. |
404 | 14040040 | purchaseNotFound | The purchaseId passed as a URL Parameter was not found. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
LiabilityWaivers
Liability Waivers
Some subscribers require new users to agree to a liability release or liability waiver. If the selected location’s subscriber.hasLiabilityWaiver
is true
, we recommend that you collect the user’s signature for the subscriber’s configured liability waiver text. This reduces friction in the user’s initial interaction with the business by collecting their signature prior to their arrival at the location.
GET
curl -X GET \
-H "API-Key: {yourAPIKey}" \
-H "Authorization: Basic {yourEncodedClientKeyAndClientSecret}" \
-A "{yourAppName}" \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/liabilitywaivers
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/liabilitywaivers");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/liabilitywaivers');
$request->setMethod(HTTP_METH_GET);
$request->setHeaders(array(
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}"
}
conn.request("GET", "/api/v1/locations/{locationId}/liabilitywaivers", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/liabilitywaivers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/locations/{locationId}/liabilitywaivers
This endpoint pulls a subscriber’s liability waiver text.
Best Practices
- Use after calling POST Booking if the location where the user booked has a liability waiver.
- Use to present a sign-able liability waiver to the end-user.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
URL Parameters
Name | Type | Description |
---|---|---|
locationId | number | The globally unique ID of a location that belongs to the subscriber from which you are pulling a liability wavier. |
Response
HTTP Status Code: 200 OK
{
"location": {
"id": 13540,
"name": "ACME Yoga",
"subscriber": {
"id": 1354158,
"name": "ACME Yoga"
},
"olsonTimeZone": "America/Los_Angeles"
},
"liabilityWaiverText": "ACME Yoga is not responsible for any damage done to your body on our premises.",
"liabilityWaiverHashedText": "21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64"
}
Name | Type | Description |
---|---|---|
location | object | Contains information about the location you passed in the request URL. |
location.id | integer | The location’s globally unique ID. |
location.name | string | The location’s name. |
location.subscriber | object | Contains information about the subscriber to whom the location and liability waiver belong. |
location.subscriber.id | integer | The subscriber’s globally unique ID. |
location.subscriber.name | string | The subscriber’s name. |
location.olsonTimeZone | string | The location’s time zone in Olson format (e.g., "America/Los_Angeles" ). Possible time zones. |
location.liabilityWaiverText | string | The liability waiver text for the associated subscriber. This string may contain HTML. |
location.liabilityWaiverHashedText | string | A hash of the liabilityWaiverText . You can compare these values to quickly identify if a change has been made in the liability waiver text. |
Errors
Example Error:
{
"error": {
"errorCode": "14040003",
"errorType": "liabilityWaiverNotFound",
"message": "This business has not yet created a liability waiver that can be signed online."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
404 | 14040001 | locationNotFound | The locationId passed as a URL Parameter was not found. |
404 | 14040003 | liabilityWaiverNotFound | The subscriber has not yet configured their liability waiver text. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
POST
curl -X POST \
-H 'api-key: {yourAPIKey}' \
-H 'authorization: Basic {yourEncodedClientKeyAndClientSecret}' \
-H 'content-type: application/json' \
-A "{yourAppName}" \
-d '{
"bookingId": "f5405d87-46a0-4b48-a384-e26159e130d6",
"liabilityWaiverHashedText": "21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64",
"pngBase64UserSignaturePicture": "{base64EncodedPngImageByteArray}"
}' \
"https://mb-api.mindbodyonline.com/affiliate/api/v1/signedliabilitywaivers"
var client = new RestClient("https://mb-api.mindbodyonline.com/affiliate/api/v1/signedliabilitywaivers");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Basic {yourEncodedClientKeyAndClientSecret}");
request.AddHeader("api-key", "{yourAPIKey}");
request.AddParameter("application/json", "{\n\t\"bookingId\": \"f5405d87-46a0-4b48-a384-e26159e130d6\",\n\t\"liabilityWaiverHashedText\": \"21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64\",\n\t\"pngBase64UserSignaturePicture\": \"{base64EncodedPngImageByteArray}\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
<?php
$request = new HttpRequest();
$request->setUrl('https://mb-api.mindbodyonline.com/affiliate/api/v1/signedliabilitywaivers');
$request->setMethod(HTTP_METH_POST);
$request->setHeaders(array(
'content-type' => 'application/json',
'authorization' => 'Basic {yourEncodedClientKeyAndClientSecret}',
'api-key' => '{yourAPIKey}'
));
$request->setBody('{
"bookingId": "f5405d87-46a0-4b48-a384-e26159e130d6",
"liabilityWaiverHashedText": "21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64",
"pngBase64UserSignaturePicture": "{base64EncodedPngImageByteArray}"
}');
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>
import http.client
conn = http.client.HTTPSConnection("mb-api.mindbodyonline.com")
payload = "{\n\t\"bookingId\": \"f5405d87-46a0-4b48-a384-e26159e130d6\",\n\t\"liabilityWaiverHashedText\": \"21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64\",\n\t\"pngBase64UserSignaturePicture\": \"{base64EncodedPngImageByteArray}\"\n}"
headers = {
'api-key': "{yourAPIKey}",
'authorization': "Basic {yourEncodedClientKeyAndClientSecret}",
'content-type': "application/json"
}
conn.request("POST", "/affiliate/api/v1/signedliabilitywaivers", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://mb-api.mindbodyonline.com/affiliate/api/v1/signedliabilitywaivers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["api-key"] = '{yourAPIKey}'
request["authorization"] = 'Basic {yourEncodedClientKeyAndClientSecret}'
request["content-type"] = 'application/json'
request.body = "{\n\t\"bookingId\": \"f5405d87-46a0-4b48-a384-e26159e130d6\",\n\t\"liabilityWaiverHashedText\": \"21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64\",\n\t\"pngBase64UserSignaturePicture\": \"{base64EncodedPngImageByteArray}\"\n}"
response = http.request(request)
puts response.read_body
https://mb-api.mindbodyonline.com/affiliate/api/v1/signedliabilitywaivers
This endpoint uploads an image of the user’s signature, verifying that they have signed the location’s liability waiver. Once signed for one location, a waiver is valid for all locations that belong to the same subscriber.
Best Practices
- Use after completing a booking. Uploading a user’s waiver signature can speed up their front-desk experience at the subscriber.
- Use after calling POST Booking.
- Use after calling GET LiabilityWaivers if you collected the user’s signature and need to save it to the subscriber.
Headers
Name | Type | Description |
---|---|---|
API-Key | string | Your API key. |
Authorization | string | Your encoded client key and client secret. See Authentication and Security for help creating this string. |
Content-Type | string | Defines the format of the request so the API can correctly process it. application/json is the only accepted value at this time. |
Request Body
{
"bookingId": "f5405d87-46a0-4b48-a384-e26159e130d6",
"liabilityWaiverHashedText": "21A951F270098C71D8C127EC57B31FDA811B37E64ABF28DD1906F84159C73D64",
"pngBase64UserSignaturePicture": "{base64EncodedPngImageByteArray}"
}
Name | Type | Description |
---|---|---|
bookingId | Guid | The ID of the booking that belongs to the subscriber for which you are submitting a liability waiver signature. |
liabilityWaiverHashedText | string | A hash of the liability waiver’s text. |
pngBase64UserSignaturePicture | string | A PNG image of the user’s signature, converted to bytes and Base64 encoded. |
Response
HTTP Status Code: 200 OK
{
"status": "Liability Waiver has been signed successfully."
}
This is the only success status message currently returned from this endpoint.
Errors
Example Error:
{
"error": {
"errorCode": "14000005",
"errorType": "invalidValue",
"message": "The following value is invalid: liabilityWaiverHashedText."
}
}
This endpoint may return the errors listed below. We recommend that you catch and handle each error for an optimal, frictionless user experience. We also recommend attempting to reproduce each error during your development and test process in order to ensure that your back-end application is handling them correctly.
HTTP Status Code | errorCode | errorType | Description |
---|---|---|---|
400 | 14000003 | missingRequiredProperty | Returned when one of the required request properties is null or empty. Check the error’s message property to find the name of the invalid property. |
400 | 14000005 | invalidValue | Returned when a request body property:
message property to find the name of the invalid property. This error may be returned if the liability waiver’s text has change since last you retrieved its hash. |
400 | 14040020 | bookingNotFound | The bookingId passed in the request body was not found. |
401 | 14010001 | missingAPIKeyHeader | An API-Key header was not included in the request. |
401 | 14010002 | missingAuthorizationHeader | An Authorization header was not included in the request. |
409 | 14090030 | subscriberUserDataMismatch | Returned when the user’s account at the subscriber has been altered in a way that prevents actions being taken on that user. |
415 | 14150002 | unsupportedMediaType | A Content-Type header was passed with a value other than application/json . This is the only accepted content type for this endpoint. |
429 | 14290001 | tooManyRequests | You have exceeded the rate limit for this endpoint. |
429 | 14290002 | dailyRequestLimitExceeded | You have exceeded the daily request limit for this endpoint. |
500 | 15009998 | criticalServerErrorLiabilityWaivers | The user’s signature was successfully stored at the subscriber, but something prevented us from tracking this information against your Affiliate account. Please move your integration out of a live environment and contact Mindbody developer support immediately. |