Group & class bookings

Table of contents:

Introduction

Through the /booking endpoint you are able to set up groups and classes, so that multiple customers can sign up for the same event. You can use the Timekit API to manage everything from your meetings and sales calls to your webinars and yoga classes. Speaking of! Let's have a look at how you would use Timekit to manage the yoga studio you've always wanted to open:

What is a group booking?

Timekit offer many different booking flows, each represented as a graph. When you are working with group bookings, you are interacting with two different graphs: The group_owner graph and the group_customer graph.

The group_owner graph is used to reserve a time slot in the owners's calendar and make it available for customers to book as a group. You can think of this as the owners availability. If you are going to offer a yoga class on Friday at 7pm, you simply need to add a booking using the group_owner graph.

When a group booking is set up, customers can book a seat. This is done using the group_customer graph. Customers can sign up for a group booking until there are no available seats left.

1. Define availability

Before customers can sign up to our yoga class, we need to configure our availability as owner. This is done by adding a owner booking using the group_owner graph.

Set up availability

For this example Doc Brown (Yes! That Doc Brown) is offering a yoga class with 20 seats, at his yoga studio on Sesame St. Middleburg, FL 32068, USA. It takes place on September 30, 2016 at 9:00 - and you don't want to miss it!

Using the group_owner graph, we can use the following request to set up the class:

# Request example (replace :calendar-id)
# [POST] /bookings
curl --request POST \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "graph": "group_owner",
          "settings": {
            "max_seats": 20
          },
          "event": {
            "start": "2016-09-30T08:00:00+00:00",
            "end": "2016-09-30T09:00:00+00:00",
            "what": "Doc Brown's Friday Yoga Class",
            "where": "Sesame St, Middleburg, FL 32068, USA",
            "calendar_id": "replace-with-id",
            "description": "Please arrive 10 minutes before classes begin"
          }
        }' \
     https://api.timekit.io/v2/bookings

Notice that we are using RFC3339 standard for the timestamp.

Now, the yoga class will be available for customers to sign up for. Hurry up before it sells out!

Optionally, you can specify some basic rules for when customers can sign up to your groups. Doc wants you to cancel at least a day before the class begins, book it no more than 14 days in advance and no later than 2 hours before. We can set it up like this:

# Request example (replace :calendar-id)
# [POST] /bookings
curl --request POST \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "graph": "group_owner",
          "settings": {
            "max_seats": 20,
            "min_cancel_time": "1 day",
            "min_booking_time": "2 hours",
            "max_booking_time": "14 days"
          },
          "event": {
            "start": "2016-09-30T08:00:00+00:00",
            "end": "2016-09-30T09:00:00+00:00",
            "what": "Doc Brown's Friday Yoga Class",
            "where": "Sesame St, Middleburg, FL 32068, USA",
            "calendar_id": "replace-with-id",
            "description": "Please arrive 10 minutes before classes begin"
          }
        }' \
     https://api.timekit.io/v2/bookings

📘

Setting up multiple groups at once?

If you are setting up multiple groups at once, say a yoga class every Friday for the next 10 weeks, you will need to call the /bookings endpoint 10 times. We are working on a version of our /findtime endpoint to allow you to query availability in bulk.

Query availability

When customers visit Doc's website, we want them to see all his classes. Technically speaking, we want to list all his group bookings that are still in a tentative state - meaning that they are neither completed, nor cancelled. We can use the /bookings/groups endpoint to query Doc's availability. That looks like this:

# Request example
# [GET] /bookings/search
curl --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     https://api.timekit.io/v2/bookings/groups

And will return something like this:

{
  "data": [
    {
      "id": "0dad9c8f-2801-4b6f-b898-7c69063bed0d",
      "state": "tentative",
      "graph": "group_owner",
      "completed": false,
      "created_at": "2016-02-11T12:39:45+0100",
      "updated_at": "2016-02-11T13:12:01+0100",
      "attributes": {
        "event_info": {
          "start": "2016-09-30T08:00:00+00:00",
          "end": "2016-09-30T09:00:00+00:00",
          "what": "Doc Brown's Friday Yoga Class",
          "where": "Sesame St, Middleburg, FL 32068, USA",
          "calendar_id": "replace-with-id",
          "description": "Please arrive 10 minutes before classes begin"
        },
        "group_booking": {
          "current_seats": 0,
          "max_seats": 20,
        }
      }
    },
    {
      "id": "a1ebdd9d-db42-4cd3-a915-0202a034284a",
      "state": "tentative",
      "graph": "group_owner",
      "completed": false,
      "created_at": "2016-02-11T12:39:45+0100",
      "updated_at": "2016-02-11T13:12:01+0100",
      "attributes": {
        "event_info": {
          "start": "2016-10-07T08:00:00+00:00",
          "end": "2016-10-07T09:00:00+00:00",
          "what": "Doc Brown's Friday Yoga Class",
          "where": "Sesame St, Middleburg, FL 32068, USA",
          "calendar_id": "replace-with-id",
          "description": "Please arrive 10 minutes before classes begin"
        },
        "group_booking": {
          "current_seats": 0,
          "max_seats": 20,
        }
      }
    }
  ]
}

Looks like no one signed up so far!? Guess there's still time to sign up. Let's do it!

You can optionally specify a start and end query parameter, to only get bookings within a given period of time.

🚧

Is it safe to expose booking data?

If you publicly expose information about a group booking (similar to what we do in our Booking.js widget), you should always use the /bookings/groups endpoint, as opposed to the regular /booking endpoint. This endpoint excludes all sensitive information about the group, such as customer information.

2. Sign up for a group booking

It appears that a certain Marty McFly is interesting in joining the yoga class. I'm sure Doc will be pleased to know, so let's sign him up using the group_customer graph:

# Request example
# [POST] /bookings
curl --request POST \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "graph": "group_customer",
          "related": {
            "owner_booking_id": "a1ebdd9d-db42-4cd3-a915-0202a034284a"
          },
          "customer": {
            "name": "Marty McFly",
            "email": "[email protected]"
          }
        }' \
     https://api.timekit.io/v2/bookings

Only 19 spots left now. Hurry up!

It's possible for customers to book more than one seat at once, so actually, let's make that 18, because Marty is bringing a friend. This can be indicated with the seats option in our request:

# Request example
# [POST] /bookings
curl --request POST \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "graph": "group_customer",
          "action": "create",
          "related": {
            "owner_booking_id": "a1ebdd9d-db42-4cd3-a915-0202a034284a",
            "seats": 2
          },
          "customer": {
            "name": "Marty McFly",
            "email": "[email protected]"
          }
        }' \
     https://api.timekit.io/v2/bookings

Marty will now have reserved 2 seats out of the 20 available ones.

3. Cancellations

Imagine a situation where Marty messed up his schedule (could you see this happen!?) and double booked himself. He would have to cancel yoga... Fortunately, that's pretty simple using the cancel_by_customer action and he can even send a message to Doc:

# Request example
# [PUT] /bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer
curl --request PUT \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "cancel_by_customer": {
            "message": "Double booked. Sorry, Doc!"
          }
        }' \
     https://api.timekit.io/v2/bookings/9d3fc349-5605-4bbf-a8fd-270fee55c137/cancel_by_customer

Even worse, Doc might have to cancel too! Then no one would get to yoga that Friday. That's done directly on the owner booking with the cancel action:

# Request example
# [PUT] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel
curl --request PUT \
     --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     --data '{
          "cancel": {
            "message": "Getting the DeLorean fixed that day. Doc."
          }
        }' \
     https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a/cancel

Marty, and everyone else who signed up, will receive a notification with Doc's message attached. All is well!

4. Manage a group booking

Before class, Doc needs to know how many yoga mats to bring. When we request the owner booking, we can ask the API to include all related customer bookings. It looks like this:

# Request example
# [GET] /bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a
curl --user :live_api_key_7nzvc7wsBQQISLeFSVhROys9V1bUJ1z7 \
     https://api.timekit.io/v2/bookings/a1ebdd9d-db42-4cd3-a915-0202a034284a?include=attributes,related_bookings

And returns something like:

{
  "data": {
    "id": "0dad9c8f-2801-4b6f-b898-7c69063bed0d",
    "state": "tentative",
    "graph": "group_owner",
    "completed": false,
    "created_at": "2016-02-11T12:39:45+0100",
    "updated_at": "2016-02-11T13:12:01+0100",
    "attributes": {
      "event_info": {
        "start": "2016-09-30T08:00:00+00:00",
        "end": "2016-09-30T09:00:00+00:00",
        "what": "Doc Brown's Friday Yoga Class",
        "where": "Sesame St, Middleburg, FL 32068, USA",
        "calendar_id": "replace-with-id",
        "description": "Please arrive 10 minutes before classes begin"
      },
      "group_booking": {
        "current_seats": 2,
        "max_seats": 20
      }
    },
    "related_bookings": [
  	  {
  			"id": "9d3fc349-5605-4bbf-a8fd-270fee55c137",
        "state": "confirmed",
        "graph": "group_customer",
        "completed": false,
        "created_at": "2016-02-11T12:39:45+0100",
        "updated_at": "2016-02-11T13:12:01+0100"
  		},
  		{
  			"id": "63550652-6b21-446c-b125-9a4d02bf6747",
        "state": "confirmed",
        "graph": "group_customer",
        "completed": false,
        "created_at": "2016-02-11T12:39:45+0100",
        "updated_at": "2016-02-11T13:12:01+0100"
  		}
    ]
  }
}

Because each customer who signs up to a group booking has an actual booking (following the group_customer_graph), related_bookings is a reference to all the customer bookings attached to the group.

Great scott, you've finished our guide! We hope that group bookings make sense to you and that you are ready to dive in. If not, hit us up on the chat and we'll help you get started.