Adding a customer on to an existing group booking

From our API's perspective, booking a customer onto an existing group booking is no different from creating a "new" booking. This means that if you are building a UI/UX around our API you do not need to concern yourself with or modify your requests to book onto either existing group bookings or "new" bookings.

If you simply want to book your customers without distinguishing between "new" bookings and existing group bookings you can follow the Creating a new booking guide, which will automatically book on to an available group booking if there is one available.

This guide covers booking onto a specific group booking, which involves the following process:

  1. Retrieving the Service ID, Resource ID, and Start Time of the target group booking.
  2. Creating a new availability slot, which reserves a set number of spaces on the target group booking for a preset number of minutes.
  3. Converting the availability slot you created in the previous step into a confirmed participant on the target group booking.

Preparing your requests

Let's setup the basic options we'll use for all of our HTTP requests to the Appointedd API. If you're testing using something like cURL you can skip this step.

const axios = require("axios").default;

const request = axios.create({
  baseURL: "https://api.appointedd.com/v1/",
  headers: {
    "X-API-KEY": "<YOUR_API_KEY>",
  },
});

Retrieving the Service ID, Resource ID, and Start Time

Obtaining the information without a Booking ID

If you don't have the Booking ID of your target group booking you can use the Find Available Intervals endpoint which allows you to search for available dates and times for resources assigned to a particular resource. This does require you to know which service in your organisation is assigned to your target group booking.

If you do not know the Service ID you can find it using the Get Services endpoint to identify the ID by matching it by the name of the service. If you do not have the ability to select services in your front-end or if you will always know which service you will be using, you can hardcode this ID into your application.

# Example Request
curl --request GET \
     --url 'https://api.appointedd.com/v1/services?limit=1' \
     --header 'Accept: application/json' \
     --header 'X-API-KEY: <API_KEY>'

# Example Response
{
  "data": [
    {
      "id": "628b68cd869f3620ef1a1ff1",
      "category_id": "628b6896e500170e850a0fe6",
      "name": "Test Service",
      "booking": {
        "occupancy": 1,
        "type": "ONLINE_BOOKING",
        "buffers": {
          "before": 0,
          "after": 0
        },
        "durations": [
          {
            "default": true,
            "minutes": 120,
            "price": 0,
            "old_price": 0
          },
        ],
        "tiers": [],
        "allow_group": true
      },
      "description": "This is a test service."
    }
  ],
  "total": 20,
  "prev": null,
  "next": "620f8dea5fe063b1e7dffec4"
}

Once you have a service ID you can make an availability search request using the Find Available Intervals endpoint. Since this endpoint only lets you search for a range that spans at most 59 days, you'll need to make multiple requests to search a larger range by splitting up the larger range into chunks.

If you are planning on booking more than 1 space you should also change the spaces property in the request to the number of spaces you require to ensure that only group bookings that have enough spaces available are returned.

# Example Request

curl --request POST \
     --url https://api.appointedd.com/v1/availability/intervals/search \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --header 'X-API-KEY: <API_KEY>' \
     --data '
{
     "ranges": [
          {
               "start": "2022-05-01T00:00:00.000Z",
               "end": "2022-06-01T00:00:00.000Z"
          }
     ],
     "spaces": 1,
     "timezone": "Europe/London",
     "service_id": "<SERVICE_ID>"
}
'
# Example Response

{
  "data": [
    {
      "start": "2022-05-26T11:30:00.000+01:00",
      "resource_ids": [],
      "group_bookings": [
        {
          "id": "628f4954645194000e770abd",
          "resource_id": "6058b50f3b5d2716e16e5db3",
          "service_id": "5e53af1e95cff00acb3976b1",
          "start": "2022-05-26T11:30:00.000+01:00",
          "start_buffer": "2022-05-26T11:30:00.000+01:00",
          "end": "2022-05-26T12:30:00.000+01:00",
          "end_buffer": "2022-05-26T12:30:00.000+01:00",
          "parts": [
            {
              "start": "2022-05-26T11:30:00.000+01:00",
              "end": "2022-05-26T12:30:00.000+01:00"
            }
          ],
          "spaces": 5,
          "price": 0,
          "resources": [
            {
              "id": "6058b50f3b5d2716e16e5db3"
            }
          ]
        }
      ],
      "group_slots": []
    }
  ]
}
const findAvailableStartDateTime = async () => {
  // Find and available date and time to create a booking for a specific
  // service with a resource in your organisation.
  const availabilityResponse = await request.post(
    "/availability/intervals/search",
    {
      ranges: [
        {
          start: "2021-01-01T00:00:00.000Z",
          end: "2021-02-01T00:00:00.000Z",
        },
      ],
      service_id: SERVICE_ID,
    }
  );

  return availabilityResponse.data.data[0].start;
};

Here you can see that there's a group booking at 2022-05-26T11:30:00.000+01:00. If there were multiple group bookings at the same time but for different resources, you would also need to note down the resource_id of the group booking you wanted to book on to.

Obtaining the information with a Booking ID

If you have the Booking ID of your target group booking you can use the Get Bookings endpoint to retrieve that information.

# Example Request
curl --request GET \
     --url 'https://api.appointedd.com/v1/bookings?ids=<GROUP_BOOKING_ID> \
     --header 'Accept: application/json' \
     --header 'X-API-KEY: <API_KEY>'

# Example Response
{
  "data": [
    {
      "id": "628f4954645194000e770abd",
      "service": "5e53af1e95cff00acb3976b1",
      "resource": "6058b50f3b5d2716e16e5db3",
      "customers": [],
      "start": "2022-05-26T10:30:00.000+00:00",
      "end": "2022-05-26T11:30:00.000+00:00",
      "start_buffer": "2022-05-26T10:30:00.000+00:00",
      "end_buffer": "2022-05-26T11:30:00.000+00:00",
      "price": 0,
      "total_spaces": 5,
      "status": "confirmed",
      "updated": "2022-05-26T09:33:08.009+00:00",
      "created": "2022-05-26T09:33:08.009+00:00",
      "created_source": "appointment_screen"
    }
  ],
  "total": 1,
  "prev": null,
  "next": null
}
const getBookingInfo = async (id) => {
  const bookingsResponse = await request.get("/bookings", {
    params: {
      ids: [id]
    }
  });
  
  return {
    id: bookingsResponse.data.data[0].id,
    resource: bookingsResponse.data.data[0].resource,
    service: bookingsResponse.data.data[0].service,
    start: bookingsResponse.data.data[0].start,
  };
}

The response will include the information required which you can use in the next step:

  • service - The ID of the service of your target group booking.
  • resource - The ID of the resource of your target group booking.
  • start - The start date and time of your target group booking.

Creating a new availability slot to reserve space on the existing group booking

From here on out the steps are exactly identical to creating a "new" booking so you can follow the steps outlined in the Creating a new booking guide, but they are described here as well.

To create an availability slot you can use the Create Reservation endpoint. Again if you need to reserve more than 1 space you should set the required_spaces property in your request appropriately.

# Example Request

curl --request POST \
     --url https://api.appointedd.com/v1/availability/slots \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --header 'X-API-KEY: <API_KEY>' \
     --data '
{
     "data": {
          "timezone": "Europe/London",
          "required_spaces": 1,
          "start": "<GROUP_BOOKING_START_TIME>",
          "service_id": "<GROUP_BOOKING_SERVICE_ID>",
          "resource_id": "<GROUP_BOOKING_RESOURCE_ID>"
     }
}
'

# Example Response

{
  "data": {
    "id": "628f52d219e956000e6d192b",
    "resource_id": "6058b50f3b5d2716e16e5db3",
    "service_id": "5e53af1e95cff00acb3976b1",
    "resources": [
      {
        "id": "6058b50f3b5d2716e16e5db3"
      }
    ],
    "booking_id": "628f4954645194000e770abd",
    "start": "2022-05-26T10:30:00.000Z",
    "start_buffer": "2022-05-26T10:30:00.000Z",
    "end": "2022-05-26T11:30:00.000Z",
    "end_buffer": "2022-05-26T11:30:00.000Z",
    "parts": [
      {
        "start": "2022-05-26T10:30:00.000Z",
        "end": "2022-05-26T11:30:00.000Z"
      }
    ],
    "expiry": "2022-05-26T10:33:38.186Z",
    "max_spaces": 5,
    "reserved_spaces": 1,
    "allow_additional_spaces": true,
    "created": "2022-05-26T10:13:38.186Z",
    "updated": "2022-05-26T10:13:38.186Z"
  }
}

Store the id as this is the ID of the reservation that you'll need to use in the next step to turn it into booking on the target group booking.

By default the reservation will expire after a preset amount of time configured in your organisation. This should give you enough time to collect your customer's details in your booking flow. If you already have the details that you require from your customer you can proceed immediately to the next step.

Confirming the availability slot and turning it into a booking

The final step is to confirm the availability slot and turn it into a booking on the target group booking using the Create Booking endpoint. This will require the ID of the availability slot you created in the previous step and at minimum the first and last name of the customer you are booking in.

# Example Request

curl --request POST \
     --url https://api.appointedd.com/v1/bookings \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --header 'X-API-KEY: <API_KEY>' \
     --data '
{
     "timezone": "Europe/London",
     "data": {
          "customers": [
               {
                    "customer": {
                         "profile": {
                              "firstname": "Ada",
                              "lastname": "Lovelace"
                         }
                    }
               }
          ]
     },
     "slot_id": "628f52d219e956000e6d192b"
}
'

# Example Response

{
  "data": {
    "id": "628f4954645194000e770abd",
    "service_id": "5e53af1e95cff00acb3976b1",
    "resource_id": "6058b50f3b5d2716e16e5db3",
    "allow_external_customers": true,
    "customers": [
      {
        "customer_id": "628f5577e55379000e8b0f04",
        "payment_ids": [],
        "customer_booking_id": "628f5577e55379000e8b0f08",
        "booking_source": "api",
        "status": "No Status",
        "locale": "en",
        "spaces": 1,
        "total_spaces": 1,
        "timezone": "Europe/London",
        "total_price": 0,
        "tier": {},
        "price_points": [
          {
            "price_per_quantity": 0,
            "spaces_per_quantity": 1,
            "quantity": 1
          }
        ],
        "reschedule_url": "https://reschedule.appointedd.com?token=d4e81bb2beb3c1f858b640cfc552d2c015aa25c1caed10663fd7b3d01e8a2fd6&bookingId=628f4954645194000e770abd&participantId=628f5577e55379000e8b0f08",
        "created": 1653560695
      }
    ],
    "created_source": "appointment_screen",
    "created": "2022-05-26T10:33:08.009+01:00",
    "updated": "2022-05-26T10:33:08.009+01:00",
    "label": "Test Basic Basic",
    "location": null,
    "start": "2022-05-26T11:30:00.000+01:00",
    "start_buffer": "2022-05-26T11:30:00.000+01:00",
    "end": "2022-05-26T12:30:00.000+01:00",
    "end_buffer": "2022-05-26T12:30:00.000+01:00",
    "buffers": {
      "before": "0",
      "after": "0"
    },
    "parts": [
      {
        "start": "2022-05-26T11:30:00.000+01:00",
        "end": "2022-05-26T12:30:00.000+01:00",
        "label": null
      }
    ],
    "status": "confirmed",
    "price": 0,
    "total_spaces": 5,
    "resources": [
      {
        "_id": "6058b50f3b5d2716e16e5db3"
      }
    ]
  }
}

This should return the details of the booking, and you're done!