The Microsoft Graph team is committed to providing booking infrastructure through the Bookings APIs so that customers can build robust customized solutions. We have been listening to customers and have received many requests for new features. Based on this feedback, we have launched some key new features such as SMS notifications, online meetings, group appointments and custom questions.
SMS notifications
SMS notifications have always been one of the major asks of customers across industries like healthcare, retail, and finance because reaching consumers is often more convenient through SMS notifications. Recently, we went GA with a SMS notification feature in the United States and Canada. Today, we are excited to announce the addition of SMS notification support in the Bookings API. Currently, this feature is only available for customers in US and Canada on Bookings Calendars created in the NAM region. We will look to expand availability to other countries in the future.
SMS notifications can be enabled for a bookingService and at a bookingAppointment level as well, with the bookingAppointment level setting taking precedence.
Attribute | Resource Type | Description |
smsNotificationsEnabled | bookingService | Indicates if SMS is enabled for the service |
smsNotificationsEnabled | bookingAppointment | Indicates if SMS is enabled for the appointment |
Online meetings
Support for online meetings was launched for our web and Team’s apps. It has been one of the key features of Bookings and has seen tremendous growth over the last couple of years. Now, one can enable online meetings for a bookingService via APIs. For an appointment of such a service, a Team’s meeting link will be auto generated. This link is part of the appointment resource type and can be accessed via APIs.
Attribute | Resource Type | Description |
isLocationOnline | bookingService | Indicates if the meeting is online |
joinWebUrl | bookingAppointment | The URL to join the online meeting |
Staff and customer time zones
The bookingAppointment resource type has an attribute for customer timezone and the bookingStaffMember resource type has an attribute for the staff timezone.
Attribute | Resource Type | Description |
customerTimeZone | bookingAppointment | Timezone of the customer for the appointment |
timeZone | bookingStaffMember | Timezone of the staff member |
Enhanced bookingCustomer resource type
We have enhanced the resource type to bring it at par with our webapp in which one can add and view additional customer properties such as address and phone number. The following new attributes have been added.
Attribute | Resource Type | Description |
location | bookingCustomer | The address of the customer. Location is of type physicalAddress. However only the “other” address type is supported. |
phone | bookingCustomer | The phone number of the customer |
Custom questions
Custom questions are one of the key features of Bookings. It can be used to collect additional information in an appointment.
Custom questions are created for a ‘bookingBusiness’ resource type. They can be attached to bookingServices resource type of that bookingBusiness. Finally, a bookingAppointment of these bookingServices will contain the custom questions and answers to those question.
CRUD operations can be done on custom questions via APIs.
Example of CRUD operations for custom questions
Retrieve a custom question object
GET https://graph.microsoft.com/beta/bookingBusinesses/<businessId>/customQuestions/<questionId> HTTP/1.1 200 OK { "id": "3bc6fde0-4ad3-445d-ab17-0fc15dba0774", "displayName": "What is your age", "answerInputType": "text", "answerOptions": [] }
List all custom questions in a business
GET https://graph.microsoft.com/beta/bookingBusinesses/<businessId>/customQuestions HTTP/1.1 200 OK [ { "id": "", "displayName": "What’s your faviourite color", "answerInputType": "text", "answerOptions": [] }, { "id": "", "displayName": "What do you want to get from this session?", "answerInputType": "text", "answerOptions": [] } ]
Create a custom question
POST https://graph.microsoft.com/beta/bookingBusinesses/<businessId>/customQuestions { "displayName": "What is your age", "answerInputType": "text", "answerOptions": [] } HTTP/1.1 201 Created { "id": "3bc6fde0-4ad3-445d-ab17-0fc15dba0774", "displayName": "What is your age", "answerInputType": "text", "answerOptions": [] }
Update a custom question
PATCH https://graph.microsoft.com/beta/bookingBusinesses/<businessId>/customQuestions/<questionId> { "displayName": "What is your date of Birth" } HTTP/1.1 204 No Content DELETE https://graph.microsoft.com/beta/bookingBusinesses/<businessId>/customQuestions/<questionId> HTTP/1.1 204 NO CONTENT
Custom questions in a bookingService
One can associate any custom question in a bookingService. It can be done by using a complex type called custom questions. An example is shown below in which a service is being created with custom fields. The “isRequired” field indicates if it is mandatory to have a value for this custom field in an appointment.
POST https://graph.microsoft.com/beta/bookingBusinesses/Contosolunchdelivery@M365B489948.onmicrosoft.com/services Content-type: application/json { "@odata.type":"#microsoft.graph.bookingService", .. .. .. "customQuestions": [ { "questionId": "75fc2eaf-624f-40b2-a289-63e51a56fcf2", "isRequired": true }, { "questionId": "b90e7840-4c0c-430f-b96f-74ad9d2f64f7", "isRequired": false } ] }
Custom questions in an appointment
Within a bookingAppointment, answers to custom questions can be added for an individual customer within a customer collection. Note that depending on the setting in the service some of the answers may be mandatory.
Here, a snippet is shown where an appointment is being created with custom questions.
POST https://graph.microsoft.com/beta/bookingBusinesses/Contosolunchdelivery@M365B489948.onmicrosoft.com/appointments Content-type: application/json { "@odata.type":"#microsoft.graph.bookingAppointment", ... ... ... "customers": [ { "@odata.type":"#microsoft.graph.bookingCustomerInformation", "customerName":"Jordan Miller", ... ... "customQuestionAnswers": [ { "questionId": "75fc2eaf-624f-40b2-a289-63e51a56fcf2", "answer": "Bread", "selectedOptions": ["Bread"] } ], ... ... } } ], ... ... ... }
Here is another example where an appointment is being retrieved
GET https://graph.microsoft.com/beta/bookingBusinesses/Contosolunchdelivery@M365B489948.onmicrosoft.com/appointments/AAMkADKnAAA= Response HTTP/1.1 200 OK Content-type: application/json { "@odata.context": "https://graph.microsoft.com/beta/$metadata#bookingBusinesses('Contosolunchdelivery%40M365B489948.onmicrosoft.com')/appointments/$entity", "id": "AAMkADKnAAA=", "selfServiceAppointmentId": "00000000-0000-0000-0000-000000000000", ... ... "customers": [ { "customerId": "7ed53fa5-9ef2-4f2f-975b-27447440bc09", "customerName": "Jordan Miller", ... ... "customQuestionAnswers": [ { "questionId": "75fc2eaf-624f-40b2-a289-63e51a56fcf2", "question": "What's your favourite food", "answerInputType": "radioButton", "answerOptions": [ "Banana Bread", "Apple Pie", "Cheese Cake" ], "isRequired": true, "answer": "Apple Pie", "selectedOptions": ["Apple Pie"] } ], ... ... } } ] }
Attributes and complex types of custom questions
Attribute | Resource Type | Description |
Id | bookingCustomQuestions | The unique id |
displayName | bookingCustomQuestions | The display name for the custom question |
answerInputType | bookingCustomQuestions | The answer type. The data type is graph.answerInputType. Supported values are radio button and text. |
answerOptions | bookingCustomQuestions | This field is applicable if the answer type is radio button. This is a collection of strings |
customQuestions | bookingService | Collection of bookingQuestionAssignment for the service |
customQuestionAnswers | bookingAppointment | Collection of bookingQuestionAnswer. This collection is an attribute within a complex type bookingCustomerInformation, which itself is present in bookingAppointment. |
Attribute | ComplexType | Description |
questionId | bookingQuestionAssignment
|
The id of the custom question which is being attached to the service. |
isRequired | bookingQuestionAssignment | Indicates if the custom question answer is mandatory in the service |
questionId | bookingQuestionAnswer | The is of custom question |
question | bookingQuestionAnswer | The display name of the question when the appointment was created |
answerInputType | bookingQuestionAnswer | The answer Input type of the question at the time of creation of appointment |
answerOptions | bookingQuestionAnswer | The possible answer options of the question at the time of creation of an appointment |
isRequired | bookingQuestionAnswer | If the answer is mandatory. It reflects the value at the time of appointment creation |
answer | bookingQuestionAnswer | The answer for the question |
selectedOptions | bookingQuestionAnswer | The selected option for the question if the question was of non-text type |
Appointments with more than one customer (group appointments)
In the web app we support appointments in which more than one customer can attend. We call these appointments “group appointments”. One can set a service to support group appointments by increasing the count of attribute maximumAttendeesCount. In the bookingAppointment resource type, maximumAttendeesCount, indicates the maximum number of allowed attendees and is inherited from the same-named attribute in the bookingService resource type. The filledAttendeesCount attribute denotes the current number of customers in an appointment.
Attribute | Resource Type | Description |
maximumAttendeesCount | bookingService | Max allowed number of customers in an appointment |
maximumAttendeesCount | bookingAppointment | Max allowed number of customers in an appointment |
filledAttendeesCount | bookingAppointment | Current number of customers in an appointment |
Changes in customer information in a bookingAppointment resource type
Customer information was available at the root level in the appointment object. Since a list of customers is now supported, the information will be within a complex type. Customer information for appointments in which maximumAttendeesCount is 1 will continue to also exist at the root level in beta- however it will be deprecated.
The difference can be seen in the two code snippets below.
Old structure of bookingAppointment
Content-type: application/json { "@odata.context": "https://graph.microsoft.com/beta/$metadata#bookingBusinesses('Contosolunchdelivery%40M365B489948.onmicrosoft.com')/appointments/$entity", "id": "AAMkADKnAAA=", "selfServiceAppointmentId": "00000000-0000-0000-0000-000000000000", "customerId": "7ed53fa5-9ef2-4f2f-975b-27447440bc09", "customerName": "Jordan Miller", "customerEmailAddress": "jordanm@contoso.com", "customerPhone": "213-555-0199", "customerNotes": null, "serviceId": "57da6774-a087-4d69-b0e6-6fb82c339976", "serviceName": "Catered bento", ... ... ... }
New structure of bookingAppointment
Content-type: application/json { "@odata.context": "https://graph.microsoft.com/beta/$metadata#bookingBusinesses('Contosolunchdelivery%40M365B489948.onmicrosoft.com')/appointments/$entity", "id": "AAMkADKnAAA=", "selfServiceAppointmentId": "00000000-0000-0000-0000-000000000000", ... ... ... "customers": [ { "customerId": "7ed53fa5-9ef2-4f2f-975b-27447440bc09", "customerName": "Jordan Miller", "customerEmailAddress": "jordanm@contoso.com", "customerPhone": "213-555-0199", "customerNotes": "notes", "customQuestionAnswers": [ { "questionId": "75fc2eaf-624f-40b2-a289-63e51a56fcf2", "question": "What's your favourite food", "answerInputType": "radioButton", "answerOptions": [ "KFC", "McDonald's", "BurgerKing" ], "isRequired": true, "answer": "KFC", "selectedOptions": ["KFC"] } ], "customerLocation": { "displayName": "home", "locationEmailAddress": null, "locationUri": "", "locationType": null, "uniqueId": null, "uniqueIdType": null, "address": { "type": "home", "postOfficeBox": "", "street": "", "city": "", "state": "", "countryOrRegion": "", "postalCode": "" }, "coordinates": { "altitude": null, "latitude": null, "longitude": null, "accuracy": null, "altitudeAccuracy": null } } } ] ... ... }
The new complex type
The complex type is called bookingCustomerInformation. The “customers” attribute within appointment is a collection of this type.
Attribute | Complex Type | Description |
Id | bookingCustomerInformation | The id of the customer |
name | bookingCustomerInformation | The name of the customer |
emailAddress | bookingCustomerInformation | The email address of the customer |
phone | bookingCustomerInformation | The phone number of the customer |
notes | bookingCustomerInformation | The notes of the customer |
location | bookingCustomerInformation | The address of the customer. Location is of type physicalAddress. However only the “other” address type is supported. |
timeZone | bookingCustomerInformation | The timeZone of the customer |
We hope that these new features will help your custom applications be more comprehensive and robust. Please give us feedback and keep reaching out to us with your use cases and requests. Check out this link to find resources that will help you get started.
Stay tuned and keep following our blog for updates on our APIs.
Happy coding!
Awesome update for the API! Can we PLEASE get a native Power Automate Connector for Bookings with custom field support? This functionality is great but it does little to democratize the technology for us citizen developers 🙁
This needs to be done very quickly. Please assign resources to work on the custom field support.
Agree also, an API is a start, but we need a Power Automate connector for Bookings to make the development process easier for most non SUPER TECH programmers.
100% agreed, this really needs added ASAP!