This is the API documentation for MakePlans. MakePlans is an online booking application with support for appointments, classes and events. For more information about the application and its features see makeplans.com. All features in MakePlans are available via the API.
General Information:
- Get started
- Base API URL
- Versioning
- Data formats
- Date handling
- Custom data
- Authentication
- Identification
- Rate limiting
- Errors
- Pagination
- Examples
- Synchronisation
- API libraries
- Webhooks
API Endpoints:
- Slots
- Bookings
- People
- Services
- Events
- Resources
- Resource exception dates
- Providers
- Categories
- Webhooks
- Users
- Account
-
Read this documentation.
-
Go to Setup -> Integrations -> API. Enable the API and get the API-key.
-
Profit.
When your integration is ready to be released you can sign up for a real account.
Limitations of the test environment:
- SMS reminders are not triggered.
- Very low SMS quota.
- Requests may run slower.
- Bugs may occur during roll out of new features to be tested.
- Lower uptime.
- All financial transactions such as Stripe are performed in their respective test/sandbox environment. Other integrations are performed against real production accounts unless the integration offers a test environment.
If you are planning to integrate directly from your application to MakePlans or need to modify information in MakePlans then you must use the private API. This API requires authentication with an API-key and should not be done publicly (on a website).
The public API is available for simple read-only operations. This is useful if you want to present information from MakePlans on your website using JavaScript. Because these operations are done on a public website you can not authenticate using your API-key. With the public API you can fetch a list of services, available timeslots and initialize the booking process.
All requests are done over HTTPS. Each object in MakePlans has its own endpoints.
The base URL is https://youraccount.makeplans.com/api/
for production apps and https://youraccount.test.makeplans.net/api/
for test apps.
The current version of the API is version 1. The versioning scheme is as follows: /api/v{version_number}/
. All paths in the rest of the document uses /api/v1/
as base path.
See the API changelog for improvements and changes.
The base URL is your account booking site such as https://youraccount.makeplans.com/
. There is no versioning. Only the latest version of the API is available.
Only read-only operations such as list and show are available with the public API. If you need to modify any data please use the private API.
The API supports JSON for input and output. In addition you can specify input using form data.
The format of the output data is provided as is and the reference is this document.
All data is UTF-8.
All examples and object attributes in this documentation are JSON. They are lowercase and use underscore as separator.
To specify JSON as output use HTTP-header Accept: application/json
. Output can also be defined by using extension in the path: /resources.json
but it is recommended to use /resources
and specify output format in the HTTP-header. Multiple items are returned as an array.
To specify JSON as input use HTTP-header Content-Type: application/json
. The body must be JSON-formatted and include the object with required attributes.
To use normal form data specify HTTP-header application/x-www-form-urlencoded
. Form values should be sent like this: resource[title]=Unicorn
. To specify array values use: selected_resources[]=1337&selected_resources[]=555
. The same applies when doing a GET request with URL parameters.
All dates are specified in the ISO 8601 format. Time zone is included in the output and specified by the account. It is not necessary to specify time zone in the input as the account time zone will be used as default. The output will give a full ISO 8601 date format with time zone: YYYY-MM-DDThh:mm:ssTZD
. For input we recommend that you do not specify time zone unless needed and omit seconds: YYYY-MM-DD hh:mm
.
Custom data is stored as key/value. All values are stored as strings but we do convert boolean values and values from keys ending in _at
to datetime at output. Custom data can be added to booking, person, service, resource and event. If you are using our standard booking site and would like to store custom data to a new booking please see the custom forms documentation for details on how to customise the booking form.
Warning: Custom data is stored as one attribute. All keys and values must be present when updating. If a booking has stored custom_data
as makeplans_is=awesome
and you want to add signup=now
then you need to include both makeplans_is
and signup
with their values.
Only the private API requires authentication. If you intend to use the API on a website please use the public API which does not require authenticaiton.
Use your account API-Key to authenticate with the MakePlans API. First enable the API on the account and you will find the API-Key in the account settings.
Send the API-Key as a Bearer token using the HTTP Authorization header.
Example: Authorization: Bearer APIKEY
Deprecated: For Basic Auth use the API-Key as username and empty password.
If your application is installable by end-users you should use oAuth. However we do not yet support oAuth so please contact us if this is something you require.
You must include a User-Agent HTTP-header with the name of your application or your website so we can get in touch in case you're doing something wrong (so we may warn you before you're blocked) or something awesome (so we may congratulate you). Example: User-Agent: YourAppName
or User-Agent: example.org
.
We do various forms of rate limiting. See details for HTTP status code 429.
4xx HTTP status codes means you made a mistake and you need to adjust your request.
API usage error. This means you did something wrong and there should be a message in the body that explains it. Error message is related to specified resource. Fix it and try again.
Example response:
{
"title": [
"is a required field. Cannot be empty"
]
}
Authentication error. Response body will give explanation if there is authorisation issue or if the API is not enabled.
Please pay your bill.
Authorization error. If you are authenticated but lack permissions.
Obviously incorrect paths (/cats
) returns 404. However, even though cool URIs should not change, previously available objects, lets say /resources/666
, might have been deleted and thus return a 404 when requested. In most cases deleted resources will be returned and have a booking state or a flag that indicate that the resource is inactive or deleted.
You can perform up to 80 requests per 20 second period from the same IP address. If you exceed this limit, you'll get a 429 Too Many Requests response for subsequent requests. Check the Retry-After
HTTP-header to see how many seconds to wait before retrying the request.
System errors (aka we screwed up) returns 5xx HTTP status codes without any detailed information. We log all system errors, but please contact us if you get this response.
{
"error": "system error"
}
Maximum 50 items are returned per response for all endpoints except bookings
which returns 750. Specify page with parameter page
. Pagination is used for: bookings, events, people and resource exception dates. All other objects return all available items. Please note that currently there is no way to specify exact part of the dataset. Thus an item might appear in both page 2 and 3 if the complete dataset for the query has changed.
RFC 8288 is used for pagination linking. You will find URLs for first, prev, next and last pages in the Link
HTTP Header. In addition metadata is added in the following HTTP Headers: Current-Page
, Page-Items
, Total-Count
, Total-Pages
.
curl -u APIKEY: \
-H 'User-Agent: YourAppName' \
-H 'Accept: application/json' \
https://youraccount.test.makeplans.net/api/v1/services
To create something you have to make a POST:
curl -u APIKEY: \
-H 'User-Agent: YourAppName' \
-H 'Accept: application/json' \
-d 'service[title]=My new service!&service[interval]=40' \
-X POST \
https://youraccount.test.makeplans.net/api/v1/services
Synchronising data is hard. Please ensure you test before releasing to production. First pick either MakePlans or the other system as a master. If the other system is chosen as a master then we recommend enabling the 'confirmation by administrator' setting for bookings. The synchronisation should then retrieve unprocessed bookings and process them (confirm/decline). This will ensure you can handle any changes occurred in the other system since the last synchronisation with MakePlans. New unprocessed bookings must be processed often (every 1-5 minutes) to ensure confirmations are sent out quickly to the end-user after requesting a new reservation.
NEVER delete any data in MakePlans to make it easier to adapt to the other system. MakePlans is a customer facing booking application. End-users (stored as people) can change and cancel bookings, thus any modifications or destruction of core data should not occur. Bookings are stored with a history (log) and there is a link between a person and bookings. MakePlans make use of this data and all this data must be kept to ensure the booking process in MakePlans works as expected for the end-user.
Expect all booking and person data to be changed at any time. All changes for an object will result in a updated attribute updated_at
.
We recommend storing a timestamp retrieved from the more recently updated item from updated_at
. When the synchronisation is performed again this timestamp can be used to fetch any changes on the updated_at
attribute for the object you want to retrieve (e.g. the parameter since
for bookings).
MakePlans does not officially support API libraries but they might be useful for you. Please note that these projects are not made by MakePlans but made publicly available by other developers who have used the MakePlans API. Any questions should be made directly to the responsible developers. If you find any errors or areas of improvement please make a pull request to improve the project.
A big thanks to everyone who has contributed to these libraries!
A webhook is simply a user-defined callback in the form of an HTTP POST which is invoked when something happens. So for example whenever a new booking is created in MakePlans we can send a POST request to the URL you specify. The response will include data about the modified object.
Name | Type | Description |
---|---|---|
event | String | Type of event |
idempotency_id | String | Unique id for this webhook |
generated_at | String | When the event was initialized |
performed_by | Object | Info of the user who performed the event |
data | Object | Related object for event type |
object | String | Type of object |
id | Integer | Id of the object |
*object_type* | Object | Payload of the object |
The attributes in the data payload, 'object', 'id', and 'object_type', is also included in the root payload due to legacy reasons. Please use the data
attribute. The legacy attributes will be removed in the future.
- booking.cancelled
- booking.confirmed
- booking.created
- booking.declined
- booking.deleted
- booking.modified
- booking.verified
- event.created
- event.deleted
- event.modified
- message.processed
- person.created
- person.deleted
- person.modified
You can use wildcard to trigger all or grouped events: *
or booking.*
We include a X-MakePlans-Signature
header in the webhook request. Use this to verify the request body to ensure the request is from MakePlans and signed with your account secret. The header includes details about the signature and the signature itself. We use HMAC SHA-256 to compute this signature.
Example: X-MakePlans-Signature:sha256=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
.
You can add HTTP Basic Auth credentials or a parameter secret to the webhook URL.
We will retry after any 4xx or 5xx http status response. Maximum retries are 5. The timeout is set to 10 seconds.
Slots are not physical objects in MakePlans. It is a virtual representation of available times based on attributes from resources and services as well as various settings. So if a resource is open 8am to 4pm and selected service has interval of 60 minutes, slots will return an array of all time intervals (8am-9am, 9am-10am etc.) and indicate which resources are available.
Slots are meant for listing available times on the MakePlans booking page. You can however make bookings at any time and with any length - as long as the resource is available off course.
Name | Type | Description |
---|---|---|
timestamp | DateTime | Start |
timestamp_end | DateTime | End |
formatted_timestamp | String | Localised human readable format |
formatted_timestamp_end | String | Localised human readable format |
free | Integer | Free capacity |
available_resources | Array | Ids of resources with availability |
maximum_capacity | Integer | The maximum capacity of the available resources |
GET /services/{service_id}/slots
will return slots for specified service.
Response
[
{
"slot": {
"timestamp": "2013-03-08T10:00:00+00:00",
"timestamp_end": "2013-03-08T10:15:00+00:00",
"formatted_timestamp": "Friday, March 8, 2013, 10:00 AM",
"formatted_timestamp_end": "Friday, March 8, 2013, 10:15 AM",
"free": 1,
"available_resources": [
1,2
],
"maximum_capacity": 2
}
}
]
Name | Type | Description |
---|---|---|
from | Date | Default: today |
to | Date | Default: today |
selected_resources | Array | Default: all active providers. |
GET /services/{service_id}/next_available_date
will return the next available date within 30 days with a free slot.
Response
[
{
"available_date": "2016-02-20"
}
]
Name | Type | Description |
---|---|---|
from | Date | Default: today. |
selected_resources | Array | Default: all active providers. |
GET /services/{service_id}/available_dates
will return the available dates for the rest of the current month.
Response
[
{
"available_date": {
"date": "2021-04-01"
}
},
{
"available_date": {
"date": "2021-04-04"
}
}
]
Name | Type | Description |
---|---|---|
from | Date | Default: today. |
to | Date | Default: rest of the month. |
selected_resources | Array | Default: all active providers. |
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_by | DateTime | Automatically set |
updated_by | DateTime | Automatically set |
service_id | Integer | Not required |
event_id | Integer | Not required |
resource_id | Integer | Required |
person_id | Integer | Not required |
booked_from | Datetime | Required |
booked_to | Datetime | Required |
expires_at | Datetime | Not required |
title | String | Not required |
notes | Text | Not required |
reminder_at | DateTime | Not required |
reminded_at | DateTime | Not required |
paid_at | DateTime | Not required |
external_id | String | Not required |
google_order_number | String | Not required |
custom_data | Array | Not required |
state | String | Automatically set. See states |
active | Boolean | Automatically set |
count | Integer | Default: 1 |
collection_id | UUID | Automatically set for recurring bookings. |
status | String | Default: null. See statuses. |
person_attributes | Object | See person. Only for input. |
person | Object | See person. Only for output. |
resource | Object | See resource. Only for output. |
service | Object | See service. Only for output. |
event | Object | See event. Only for output. |
- awaiting_verification
- verification_expired
- awaiting_payment
- awaiting_confirmation
- confirmed
- declined
- cancelled
- deleted
- checked_in
- in_progress
- completed
- no_show
The normal booking flow when a customer initiates a new booking starts with awaiting_verification
. If verification is required MakePlans sends out email or SMS for the customer to verify. When successfully verified the state is updated to confirmed
or awaiting_confirmation
if reservations requires confirmation by administrator. For confirmation it is then updated to confirmed
as normally if confirmed, and to declined
if it is not confirmed.
Bookings that have been confirmed and then cancelled, either by customer or administrator, are set to cancelled
.
Bookings that are deleted are set to deleted
.
Bookings with states awaiting_verification
, awaiting_payment
, awaiting_confirmation
or confirmed
are considered to be active. Bookings with state awaiting_verification
will be updated with state verification_expired
after the current time passes expires_at
. However updating states rely on automatic tasks so you must use the active
attribute to check whether a booking is active or not. Only active bookings will be returned unless you specify: a booking by id, a specific state such as bookings that are awaiting confirmation, to return all bookings for a resource or dates, or for a person.
See query parameters for filtering the output beyond the default outputs.
GET /bookings
will return all active bookings.
GET /bookings/recent
will return all active bookings ordered based on updated_at.
GET /bookings/upcoming
will return all active bookings from and including {date}
.
GET /bookings/unconfirmed
will return only unconfirmed bookings.
GET /bookings/all
will return all bookings of all states (including declined
, cancelled
, deleted
, and verification_expired
). This is a useful output for syncronisation when you need to keep a track of deleted bookings.
GET /bookings/visible
will return all active bookings as well as those declined or cancelled. This is the preferred output if you want to provide a list of all bookings for visual presentation.
Response
[
{
"booking": {
"booked_from": "2012-09-29T07:00:00+02:00",
"booked_to": "2012-09-29T08:00:00+02:00",
"created_at": "2012-09-20T15:34:16+02:00",
"custom_data": null,
"count": 1,
"expires_at": null,
"external_id": null,
"id": 1,
"notes": "Very handsome customer",
"person_id": 1,
"resource_id": 1,
"service_id": 1,
"state": "confirmed",
"status": null,
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
Name | Type | Description |
---|---|---|
service_id | Integer or array of integers | |
event_id | Integer or array of integers | |
resource_id | Integer or array of integers | |
person_id | Integer or array of integers | |
external_id | String | |
start | DateTime | booked_from after param |
end | DateTime | booked_to before param |
since | DateTime | updated_at after param |
collection_id | UUID | |
state | String or array of strings | See states |
status | String or array of strings | See statuses |
You can return bookings of multiple resources/services/events/people with an array.
Name | Type | Description |
---|---|---|
extended | Boolean | Extend output with full data from related objects. |
GET /bookings/{booking_id}
will get booking with id {booking_id}
.
You can also find a booking with external_id
:
GET /bookings/find_by/external_id/{external_id}
will get booking with external_id {external_id}
.
POST /bookings
will create a new booking.
Bookings without person_id
are shown as busy in the calendar.
These parameters are part of booking: booking[public_booking]
.
Name | Type | Description |
---|---|---|
public_booking | Boolean | Restrict to normal public booking rules such as within opening hours, not able to book in the past or past specified allowed date in the future. Recommended for all customer facing booking applications (e.g. integration on website). Not recommended when synchronising with other calendar programs. Default: false. |
These parameters are part not of booking[]
: confirm
.
Outgoing messages requires person_id and service_id.
Default action for outgoing messages is according to the settings for booking verification. If email verification is enabled then all *_email
messages will be triggered by default to the customer. To override please see parameters for each action below. For admin notification messages the default is based on the account settings. SMS reminders is based on account settings and uses a default value for the time unless specified.
Name | Type | Description |
---|---|---|
confirm | Boolean | If set to false then the 'initiate verification' event is executed. If verification is required the state will be set to `awaiting_verification`. If no verification is required then the state will be set to `awaiting_confirmation` or `confirmed`. |
ignore_capacity | Boolean | Will force save the booking even though other bookings exists within the same time on the specified resource_id (double booking). Not applicable when `public_booking` is set to false (no double bookings allowed). Default: false. |
add_reminder_sms | Boolean | Automatically adds `reminder_at` based on setting from account attribute `sms_reminder_time`. Default: at 12PM the day before the appointment. |
add_messages | Boolean | Automatically generate messages based on message templates. (NOTE: Beta functionality available by invitation.) |
verification_send_email | Boolean | Send out verification email. Only applicable when `confirm` is set to false. |
verification_send_sms | Boolean | Send out verification SMS. Only applicable when `confirm` is set to false. |
confirmation_send_email | Boolean | Send out confirmation email. |
confirmation_send_sms | Boolean | Send out confirmation SMS. |
notification_send_email | Boolean | Send out notification email to admin. |
notification_send_sms | Boolean | Send out notification SMS to admin. |
extended | Boolean | Extend output with full data from related objects. |
To add a new person along with a booking you must populate person_attributes
with person attributes. Values will be matched to an existing person based on national id number, phone number or email (in that order).
POST /bookings/recurring
will create recurring bookings based on a pattern.
The recurrence format follows the iCalendar specification. The attributes for recurrence are: RRULE
, RDATE
, EXDATE
. For an introduction and examples of these parameters see this section from the iCalendar specification.
In the iCalendar specification the recurrence is based on values in DTSTART
and DTEND
. This is set by booked_from
and booked_to
from booking
.
All recurring bookings will except for booked_from
and booked_to
have the same attributes based on the specified parameters in booking
.
All bookings created by the recurring pattern gets the same UUID in collection_id
. As the collection name implies, and as is possible with the iCalendar specification, this is not necessarily only for recurrence (i.e. 9am-10am each Friday until December 1st) but also for multiple specific times (as can be specified with RDATE
).
Only the collection_id
is returned. No bookings are created at the time of request as they will be processed by the server in the background due to the volume of bookings that it is possible to create at one time. A successful response with a collection_id
does in no way indicate that any bookings will be created. The first booking as defined in booking
is however validated. If it is not valid errors details are returned in the same way as creating a single booking. In such a case recurring rules are not applied and you must adjust the request until validation is successful.
The parameters for recurrence are not set in booking
but in recurring
.
Name | Type | Description |
---|---|---|
rrule | String | Repeating pattern. Example: `FREQ=DAILY;UNTIL=19971224T000000Z`. |
rdate | String | List of recurring dates. Example: `VALUE=DATE:19970101,19970120,19970217,19970421`. |
exdate | String | List of dates that should be excluded from the recurring rule. Example: `VALUE=DATE:19970102`. |
You should always specify COUNT or UNTIL with RRULE. The max number of occurrences is 731, regardless if a limit is set or not.
GET /bookings/recurring/{collection_id}
will return all occurrences for a collection.
DELETE /bookings/recurring/{collection_id}
will delete all occurrences for a collection.
PUT /bookings/{booking_id}/verify
will verify a booking. The verification code is not checked. Use this when you handle verification in your application.
PUT /bookings/{booking_id}/verify_code
will verify a booking using {verification_code}
. Use this when MakePlans is used to send out verification email or SMS.
See information about additional parameters.
Name | Type | Description |
---|---|---|
confirmation_send_email | Boolean | Send out confirmation email. |
confirmation_send_sms | Boolean | Send out confirmation SMS. |
notification_send_email | Boolean | Send out notification email to admin. Default: based on account setting. |
notification_send_sms | Boolean | Send out notification SMS to admin. |
verification_code | String | Verification code send using SMS or email. Only applicable for the `verify_code` action. |
PUT /bookings/{booking_id}/confirm
will confirm a booking.
See information about additional parameters.
Name | Type | Description |
---|---|---|
confirmation_send_email | Boolean | Send out confirmation email. |
confirmation_send_sms | Boolean | Send out confirmation SMS. |
notification_send_email | Boolean | Send out notification email to admin. |
notification_send_sms | Boolean | Send out notification SMS to admin. |
PUT /bookings/{booking_id}/decline
will decline a booking.
See information about additional parameters.
Name | Type | Description |
---|---|---|
decline_send_email | Boolean | Send out decline email. |
decline_send_sms | Boolean | Send out decline SMS. |
PUT /bookings/{booking_id}/cancel
will cancel a booking.
See information about additional parameters.
Name | Type | Description |
---|---|---|
cancellation_send_email | Boolean | Send out cancellation email. |
cancellation_send_sms | Boolean | Send out cancellation SMS.. |
PUT /bookings/{booking_id}
will update a booking.
See information about additional parameters.
Name | Type | Description |
---|---|---|
ignore_capacity | Boolean | Set to true to allow a double booking. |
add_reminder_sms | Boolean | Automatically adds `reminder_at`. |
modification_send_email | Boolean | Send out modification email. |
modification_send_sms | Boolean | Send out modification SMS. |
extended | Boolean | Extend output with full data from related objects. |
DELETE /bookings/{booking_id}
will delete existing booking with id {booking_id}
.
Deleting a booking will set it to state=deleted and active=false. It will not be visible in listing, only when requesting GET /bookings/all
or by requesting the booking directly GET /bookings/{booking_id}
.
Do not use this method if the booking is rescheduled or cancelled.
See information about additional parameters.
Name | Type | Description |
---|---|---|
cancellation_send_email | Boolean | Send out cancellation email. |
cancellation_send_sms | Boolean | Send out cancellation SMS. |
PUT /bookings/{booking_id}/status
will update the booking status.
Name | Type | Description |
---|---|---|
status | String | Booking status. |
This parameter is specified in the same way as additional parameters.
The primary key for a person is id
. However the following fields are unique: email
, phonenumber
, national_id_no
and provider
+uid
. There are no specific requirements for input but a person needs to have either name, email, national id number or phone number.
It is possible to give a person ability to book on behalf of other people. This is linked through the parent_id
attribute.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
name | String | Not required. |
String | Not required. | |
phone_number | String | Not required. Phone number as stored. Also available as phonenumber (deprecated). |
phone_number_formatted | String | Only returnable. E.164 formatted phone number with plus sign, international code, and no spaces or parentheses. |
external_id | String | Not required |
custom_data | Array | Not required. Key/value. Stored as strings. |
date_of_birth | Date | Not required |
national_id_no | String | Not required. |
street | String | Not required. |
city | String | Not required. |
postal_code | String | Not required. |
state | String | Not required. |
country_code | String | Not required. ISO 3166-1 alpha-2. |
notes | Text | Not required. |
parent_id | Integer | Id of parent. |
GET /people
will return all active people.
GET /people/all
will return all people including those who are deactivated.
Response
[
{
"person": {
"created_at": "2012-09-20T15:34:16+02:00",
"custom_data": null,
"date_of_birth": null,
"email": "robot@booking.makeplans.com",
"external_id": null,
"id": 1,
"name": "Espen Antonsen",
"national_id_no": null,
"notes": null,
"phonenumber": "",
"updated_at": "2012-09-20T15:34:16+02:00",
"phone_number_formatted": null
}
}
]
You can search multiple columns at once, for example email
and phone_number
, or you can use the shorthand search
to search email, phone number, national id no or name.
Name | Type | Description |
---|---|---|
search | String | |
String | ||
phone_number | String | |
external_id | String | |
name | String | |
date_of_birth | Date | |
national_id_no | String | |
since | DateTime | updated_at after param |
GET /people/{person_id}
will get a person with id {person_id}
.
POST /people
will create a new person.
PUT /people/{person_id}
will update existing person with id {person_id}
.
DELETE /people/{person_id}
will delete existing person with id {person_id}
.
PUT /people/{person_id}/undelete
will undelete existing person with id {person_id}
.
POST /people/{person_id}/merge?merge_person_id={merge_person_id}
will merge existing person with id {person_id}
and {merge_person_id}
. All bookings for {merge_person_id}
will be transferred to {person_id}
. {merge_person_id}
will be deleted. You can also specify attributes to update with {person}
just like when creating/updating a person.
The purpose of this feature is to verify a new or existing person in MakePlans on your website such as "login to see your bookings". The verification can be done either using email or SMS. When successful you will have verified either an email or a phone number. Thus you can either create a new person or retrieve an existing person knowing that the person has been verified.
Please note that this token is perishable, meaning that it will be removed from and unavailable for verification after 10 minutes.
POST /people/perishable_token/send
will send a SMS with a five digit code (the token) or an email with a link which includes the token in the URL. Specify either person[email]
or person[phone_number]
.
Sending via email is not yet implemented. Only SMS token is possible.
POST /people/perishable_token/verify
. This will return a person if authentication is successful. If the email or phone_number is already registered to a person then that person will be returned. If no person exists with the specified email/phone_number then a empty person object will be returned. You then have to make another call to create the person. If the token and the identifier do not match an error is returned.
Specify the token as perishable_token
and the identifier in person[email]
or person[phone_number]
.
GET /people/{person_id}/bookings
will retrieve all bookings for person with id {person_id}
. You can also use other listings as described in the bookings listing such as GET /people/{person_id}/bookings/visible
to include cancelled bookings.
GET /people/{person_id}/children
will retrieve all children for person with id {person_id}
.
There are two types of services:
- Appointment
- Attendance
Appointments can be booked within fixed opening hours as specified on the Resource and with exceptions specified in ResourceExceptionDate.
Attendance at an event is also a booking but the individual booking datetime or resource cannot be modified. Attendance is linked to an event which occurs at a specific time. One service can be linked to one or multiple events.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
title | String | Required |
description | Text | |
active | Boolean | Automatically set |
booking_capacity | Integer | Not required |
day_booking_specify_time | Boolean | Not required (default false) |
has_day_booking | Boolean | Not required (default false) |
interval | Integer | Not required (default 60) |
max_slots | Integer | Not required (default 1) |
price | Decimal | Not required. |
same_day | Boolean | Not required (default false) |
template | String | Component template (calendar view) |
interval_rounding | Integer | Overrides account default (see info on account object) |
booking_type | String | Required. Values: appointment (default) or attendance |
custom_data | Array | Not required |
booking_form | Liquid-Text | Custom booking form |
mail_verification | Liquid-Text | |
mail_confirmation | Liquid-Text | |
sms_verification | Liquid-Text | |
sms_confirmation | Liquid-Text | |
sms_reminder | Liquid-Text |
Name | Type | Description |
---|---|---|
booking_type_id | Integer | 1: appointment. 2: attendance. |
GET /services/
will return all services.
Response
[
{
"service": {
"active": true,
"booking_capacity": 1,
"booking_type_id": 1,
"description": "The best service",
"created_at": "2012-09-20T15:34:16+02:00",
"custom_data": null,
"day_booking_specify_time": false,
"has_day_booking": false,
"id": 1,
"interval": 20,
"max_slots": null,
"price": "115.0",
"same_day": false,
"template": null,
"title": "Chiropractor",
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
GET /services/{service_id}
will get a service with id {service_id}
.
POST /services
will create a new service.
PUT /services/{service_id}
will update existing service with id {service_id}
.
DELETE /services/{service_id}
will delete existing service with id {service_id}
. Deleting a service will set it to active=false and will not be returned in any listings.
Unlike appointments made through a normal service events starts and ends at a specific time. An event is connected to a resource and a service. It could be either a one-off event (e.q. a concert) or something that occurs multiple times (e.q. spinning class). Event bookings have a strong relation to the event. That means that it is not possible to modify details such as {booked_from}
, {booked_to}
, {resource_id}
and {service_id}
for the {booking}
. To make such changes it must be done to the event. All bookings connected to the event will then automatically me modified.
While events are connected to a resource bookings or capacity of an event are not restricted by the opening hours or availability of a resource.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
resource_id | Integer | Required |
service_id | Integer | Required |
published | Boolean | Default: true |
capacity | Integer | Required |
starts_at | Datetime | Required |
ends_at | Datetime | Required |
custom_data | Array | Not required |
description | Text |
GET /events/
will return all events.
Response
[
{
"event": {
"capacity": 10,
"created_at": "2012-09-20T15:34:16+02:00",
"custom_data": null,
"description": null,
"ends_at": "2015-08-10T11:30:00+02:00",
"id": 1,
"resource_id": 1,
"published": true,
"starts_at": "2015-08-10T10:00:00+02:00",
"service_id": 1,
"title": "Super fun event",
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
Name | Type | Description |
---|---|---|
service_id | Integer | |
resource_id | Integer | |
start | DateTime | starts_at after param |
end | DateTime | ends_at before param |
since | DateTime | updated_at after param |
GET /events/{event_id}
will get an event with id {event_id}
.
POST /events
will create a new event.
POST /events/recurring
will create a multiple events.
The recurrence format follows the iCalendar specification. The attributes for recurrence are: RRULE
, RDATE
, EXDATE
. For an introduction and examples of these parameters see this section from the iCalendar specification.
In the iCalendar specification the recurrence is based on values in DTSTART
and DTEND
. This is set by starts_at
and ends_at
from event
.
All recurring events will except for starts_at
and ends_at
have the same attributes based on the specified parameters in event
.
All events created by the recurring pattern gets the same UUID in collection_id
. As the collection name implies, and as is possible with the iCalendar specification, this is not necessarily only for recurrence (i.e. 9am-10am each Friday until December 1st) but also for multiple specific times (as can be specified with RDATE
).
Only the collection_id
is returned. No events are created at the time of request as they will be processed by the server in the background due to the volume of events that it is possible to create at one time. A successful response with a collection_id
does in no way indicate that any events will be created. The first event as defined in event
is however validated. If it is not valid errors details are returned in the same way as creating a single event. In such a case recurring rules are not applied and you must adjust the request until validation is successful.
The parameters for recurrence are not set in event
but in recurrence
.
Name | Type | Description |
---|---|---|
rrule | String | Repeating pattern. Example: `FREQ=DAILY;UNTIL=19971224T000000Z`. |
rdate | String | List of recurring dates. Example: `VALUE=DATE:19970101,19970120,19970217,19970421`. |
exdate | String | List of dates that should be excluded from the recurring rule. Example: `VALUE=DATE:19970102`. |
You should always specify COUNT or UNTIL with RRULE. The max number of occurrences is 731, regardless if a limit is set or not.
GET /events/recurring/{collection_id}
will return all occurrences for a collection.
PUT /events/{event_id}
will update existing service with id {event_id}
.
DELETE /events/{event_id}
will delete existing event with id {event_id}
. Deleting a event will set it to active=false and will not be returned in any listings.
GET /events/{event_id}/bookings
will return all bookings for event with id {event_id}
.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
title | String | Required |
active | Boolean | Automatically set |
opening_hours_mon | Array | Default opening hours for Monday. |
opening_hours_tue | Array | Default opening hours for Tuesday. |
opening_hours_wed | Array | Default opening hours for Wednesday. |
opening_hours_thu | Array | Default opening hours for Thursday. |
opening_hours_fri | Array | Default opening hours for Friday. |
opening_hours_sat | Array | Default opening hours for Saturday. |
opening_hours_sun | Array | Default opening hours for Sunday. |
Values for the opening hours attributes is of type time in the array. Values are in the form of two's. This results in adding breaks within a day. To define opening hours from 8AM to 4PM with lunch at 12PM to 12.30PM the following array will be the result: ['08:00', '12:00', '12:30', '16:00']
. Having opening hours without a lunch break will yield this result: ['08:00', '16:00']
. To define a weekday as closed the value should be NULL
.
Name | Type | Description |
---|---|---|
open_0 | Time | Opening time for Monday |
open_1 | Time | Opening time for Tuesday |
open_2 | Time | Opening time for Wednesday |
open_3 | Time | Opening time for Thursday |
open_4 | Time | Opening time for Friday |
open_5 | Time | Opening time for Saturday |
open_6 | Time | Opening time for Sunday |
close_0 | Time | Closing time for Monday |
close_1 | Time | Closing time for Tuesday |
close_2 | Time | Closing time for Wednesday |
close_3 | Time | Closing time for Thursday |
close_4 | Time | Closing time for Friday |
close_5 | Time | Closing time for Saturday |
close_6 | Time | Closing time for Sunday |
These deprecated attributes define opening hours without breaks. Given opening_hours_tue
with a break defined as this: ['08:00', '12:00', '12:30', '16:00']
it would yield open_1
to be 08:00
and close_1'
to be 16:00
. These attributes are deprecated and will be removed in a future API version.
GET /resources/
will return all resources.
Response
[
{
"resource": {
"capacity": 1,
"created_at": "2012-09-20T15:34:16+02:00",
"id": 1,
"opening_hours_mon": ["08:00", "16:00"],
"opening_hours_tue": ["08:00", "11:00", "13:00", "17:30"],
"opening_hours_wed": ["08:00", "16:00"],
"opening_hours_thu": ["08:00", "12:00", "14:00", "20:00"],
"opening_hours_fri": ["08:00", "12:00", "12:30", "17:30"],
"opening_hours_sat": null,
"opening_hours_sun": null,
"title": "Mr. Spine Twister",
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
GET /resources/{resource_id}
will get a resource with id {resource_id}
.
POST /resources
will create a new resource.
PUT /resources/{resource_id}
will update existing resource with id {resource_id}
.
DELETE /resources/{resource_id}
will delete existing resource with id {resource_id}
. Deleting a resource will set it to active=false and will not returned in any listings.
Opening hours for specific dates is based on the standard opening hours that are specified on the resource but can be overridden with entries in resource exception dates.
GET /resources/{resource_id}/opening_hours
will get opening hours on specific dates for resource with id {resource_id}
.
Response
[
{
"resource_opening_hours": {
"date": "2015-12-03",
"opening_hours": ["10:00", "12:00"]
}
},
{
"resource_opening_hours": {
"date": "2015-12-04",
"opening_hours": null
}
}
]
Name | Type | Description |
---|---|---|
from | Date | Default: today |
to | Date | Default: today |
Opening hours for a resource is what is used to generate available slots for a service. It is based on the default opening hours on the resource unless anything else is specified by a resource exception date. So ignore the poorly naming of the feature and treat it as opening hours on dates. If a resource should be closed for a week then you would add resource exception dates. If a resource should have opening hours 08:00 to 14:00 on January 5th 2016 instead of the default opening hours for that weekday which could be 09:00 to 15:00, then add it as a resource exception date. See resource opening hours for how to specify.
Exception dates are related to a resource: GET /resources/{resource_id}/exception_dates
.
Name | Type | Description |
---|---|---|
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
resource_id | Integer | Required (specified in URL) |
exception_date | Date | Required (specified in URL) |
opening_hours | Array | Same format as resource opening hours |
GET /resources/{resource_id}/exception_dates
will return all exception dates for resource with id {resource_id}
.
Response
[
{
"resource_exception_date": {
"created_at": "2012-09-20T15:34:16+02:00",
"resource_id": 1,
"exception_date": "2014-01-08",
"opening_hours": ["08:00", "12:00", "12:30", "17:30"],
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
Name | Type | Description |
---|---|---|
from | Date | |
to | Date |
GET /resources/{resource_id}/exception_dates/{exception_date}
will get the exception date {exception_date}
for resource {resource_id}
. If no existing entry is found a 404 HTTP status code is returned. In that case standard opening hours apply.
POST /resources/{resource_id}/exception_dates/{exception_date}
will create a new or update an existing exception date {exception_date}
for resource {resource_id}
. You can also use PUT
, both methods works the same way regardless if it is a new entry or an update to an existing one.
POST /resources/{resource_id}/exception_dates/
will create new or update existing exception dates for resource {resource_id}
. You can also use PUT
, both methods works the same way regardless if it is a new entry or an update to an existing one.
To delete an existing exception date set {_destroy}
to be true.
{
"resource_exception_dates": [
{
"exception_date": "2015-10-22",
"opening_hours": [
"12:00",
"14:30"
]
},
{
"exception_date": "2015-10-25",
"opening_hours": [
"08:30",
"12:30",
"15:00",
"18:30"
]
},
{
"exception_date": "2015-10-26",
"opening_hours": [
"10:30",
"15:00"
]
},
{
"exception_date": "2015-10-27",
"opening_hours": null
},
{
"exception_date": "2015-10-28",
"_destroy": true
}
]
}
DELETE /resources/{resource_id}/exception_dates/{exception_date}
will delete existing exception date {exception_date}
for resource {resource_id}
.
Resources provides services. This link is called a provider.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
active | Boolean | Automatically set |
resource_id | Integer | Required |
service_id | Integer | Required |
GET /providers/
will return all providers.
Response
[
{
"provider": {
"created_at": "2012-09-20T15:34:16+02:00",
"id": 1,
"resource_id": 1,
"service_id": 1,
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
GET /providers/{provider_id}
will get a provider with id {provider_id}
.
POST /providers
will create a new provider.
DELETE /providers/{provider_id}
will delete existing provider with id {provider_id}
.
Services can be listed in a category. Categories can be presented like a tree. Root categories are defined with empty {parent_id}
.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
title | String | Required |
parent_id | Integer | |
custom_data | Array | Not required. |
GET /categories/
will return all categories.
Response
[
{
"category": {
"created_at": "2012-09-20T15:34:16+02:00",
"custom_data": null,
"id": 1,
"parent_id": null,
"title": "My first little category",
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
GET /categories/{category_id}
will get a category with id {category_id}
.
POST /categories
will create a new category. To add connected services specify array of {service_id}
in parameter {service_id_list}
.
PUT /categories/{category_id}
will update existing category with id {category_id}
. To add connected services specify array of {service_id}
in parameter {service_id_list}
.
DELETE /categories/{category_id}
will delete existing category with id {category_id}
.
GET /categories/{category_id}/services
will return all services for category with id {category_id}
.
For any additional usage of a service please use the main service endpoint.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
target_url | String | Required |
event | String | Required |
active | Boolean | Automatically set |
See webhook overview for a list of events, wildcard usage to trigger from multiple events, and how to handle webhook events from MakePlans.
GET /web_hooks/
will return all webhooks.
Response
[
{
"web_hook": {
"id": 1,
"target_url": "https://example.com/newcustomer/yeah",
"event": "person.created",
"active": true,
"created_at": "2012-09-20T15:34:16+02:00",
"updated_at": "2012-09-20T15:34:16+02:00"
}
}
]
GET /web_hook/{web_hook_id}
will get a webhook with id {web_hook_id}
.
POST /web_hook
will create a new webhook.
PUT /web_hook/{web_hook_id}
will update existing webhook with id {web_hook_id}
.
DELETE /web_hook/{web_hook_id}
will delete existing webhook with id {web_hook_id}
.
Information and settings for your account.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
subdomain | String | Required |
String | Required | |
name | String | Required |
google_analytics | String | |
css_url | String | |
time_zone | String | Required |
verification_method | Integer | |
address | String | |
country_code | String | Required. ISO 3166-1 alpha-2. |
google_merchant_id | String | |
google_merchant_key | String | |
logo | File | |
template | Integer | Required |
service_template | String | |
locale | String | Required. Supported locales: 'en', 'sv' and 'nb'. Default: 'en'. |
currency | String | ISO4217 currency code |
email_notification | Boolean | |
mail_notification_recipient | ||
sms_notification | Boolean | |
phone_number | String | |
confirm_manually | Boolean | |
settings | Array | |
public_access | Boolean | |
interval_rounding | Integer | Default setting for all services for rounding to next available time. '15' will round 10:07 to become 10:15 as next available slot time. |
slot_generation_type | Integer | Default: 2. 1=fixed. 2=next available. |
future_bookable_period | String | Natural language date/time relative to current time. |
first_bookable_period | String | Natural language date/time relative to current time. |
payment_provider | String | |
footer | Text | |
verification_methods | String | |
reminder_sms | Boolean | |
closed_for_holidays | Boolean | |
new_user_text | Liquid-Text | Above booking form. |
new_booking_text | Liquid-Text | Booking confirmation page. |
booking_form | Liquid-Text | Custom booking form. |
person_form | Liquid-Text | For custom data in administration system. |
resource_form | Liquid-Text | For custom data in administration system. |
service_form | Liquid-Text | For custom data in administration system. |
event_form | Liquid-Text | For custom data in administration system. |
appointment_form | Liquid-Text | For custom data in administration system. |
category_form | Liquid-Text | For custom data in administration system. |
sms_verification | Liquid-Text | |
sms_confirmation | Liquid-Text | |
sms_modification | Liquid-Text | |
sms_cancellation | Liquid-Text | |
sms_reminder | Liquid-Text | |
mail_verification | Liquid-Text | |
mail_confirmation | Liquid-Text | |
mail_modification | Liquid-Text | |
mail_cancellation | Liquid-Text | |
mail_verification_subject | String | |
mail_confirmation_subject | String | |
mail_modification_subject | String | |
mail_cancellation_subject | String | |
allow_cancellation | Boolean | |
cancellation_period | String | Natural language date/time relative to start of booking. |
Name | Type | Description |
---|---|---|
remove_logo | Boolean |
GET /client
will get the account.
PUT /client
will update the account.
Who doesn't like a holiday?
GET /client/holidays
will get holidays for account country.
Response
[
{
"holiday": {
"date": "2016-01-01",
"name": "New Year's Day"
}
},
{
"holiday": {
"date": "2016-05-01",
"name": "International Workers' Day"
}
}
]
Name | Type | Description |
---|---|---|
from | Date | |
to | Date |
Users who can login into the account.
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
user_id | Integer | Automatically set |
role | String | admin, manager or staff |
user | Object | See attributes for a user |
Name | Type | Description |
---|---|---|
id | Integer | Automatically set |
created_at | Datetime | Automatically set |
updated_at | Datetime | Automatically set |
name | String | Required |
String | Required | |
phone_number | String | Also available as phonenumber (deprecated). |
GET /client/users
will list all users with access to the account.
Response
[
{
"client_user_link": {
"id": 1337,
"created_at": "2016-11-07T07:26:32+01:00",
"updated_at": "2016-11-07T07:27:42+01:00",
"role": "admin",
"user_id": 1,
"user": {
"id": 1,
"email": "maestro@example.org",
"phone_number": "180",
"name": "Espen Antonsen",
"created_at": "2016-11-07T07:26:32+01:00",
"updated_at": "2016-11-07T07:27:42+01:00"
}
}
}
]
GET /client/users/{user_link_id}
will get a user with id {user_link_id}
.
GET /client/users
will create a new user. An email is sent to the user so the user can specify their password.