Applies to: Bookings API | Locations API | Customers API | Team API | Catalog API
Learn how to create and manage bookings for a Square seller.
You can use the Bookings API to create appointment-based applications that allow a customer of a Square seller to book an appointment for a particular service provided by the seller or one of the seller's team members. In addition to the Bookings API, you're likely to use other related Square APIs, such as the Locations API, Customers API, Team API, and Catalog API.
In general, a booking application supports a frontend as an interface with a user to let the user book an appointment for a particular service at a particular location. At various stages of the user interaction, you need to perform the following operations targeted at the backend:
- Call the Locations API to list and retrieve business locations for the user to choose from for a particular booking.
- Call the Catalog API to create, list, or search for services that can be booked by customers online.
- Call the Customers API to create or search for a customer profile representing the user to receive the service for a booking.
- Call the Bookings API to list or retrieve a booking profile of a team member who can provide a service for a booking.
- Call the Bookings API to retrieve the booking profile of a business that provides a service in a booking.
- Call the Bookings API to search for available service segments that can be booked in a booking.
- Call the Bookings API to create, inspect, or update a booking.
Depending on the permissions granted, the user might succeed in performing all or some of the actions or have access to the whole or part of resulting booking information.
In the following sections, you learn how booking data can be accessed with buyer-level and seller-level permissions and how to call the API using cURL commands.
Applications with buyer-level permissions and those with seller-level permissions create different bookings and receive different booking event data. The differences are manifested in different scopes of access to the booking data by the two types of booking applications.
The following table lists the different scopes of access to booking data, with buyer-level and seller-level permissions. Attributes with read/write access can be set when a booking is created or modified when a booking is updated. Attributes with read-only or read/write access are included in the result from RetrieveBooking or ListBookings and they're included as part of event data in the webhook notification of the booking.created or booking.updated event.
Note
When a deposit has been made to a booking, the appointment segments (as specified by the appointment_segments attribute) of the booking cannot be updated.
Object | Field | Buyer-level access | Seller-level access |
---|---|---|---|
Booking | id | Read-only | Read-only |
version | Set for optimistic locking | Set for optimistic locking | |
status | Read-only | Read-only | |
created_at | Read-only | Read-only | |
updated_at | Read-only | Read-only | |
start_at | Read/write | Read/write | |
location_id | Read/write[*] | Read/write[*] | |
address | Read/write[*] | Read/write[*] | |
customer_id | Read/write[*] | Read/write[*] | |
customer_note | Read/write | Read/write | |
seller_note | None | Read/write | |
transition_time_minutes | None | Read-only | |
all_day | Read-only | Read-only | |
creator_details | None | Read-only | |
source | None | Read-only | |
location_type | Read/write | Read/write | |
appointment_segments | Read/write[*] | Read/write | |
AppointmentSegment | duration_minutes | Read-only | Read/write |
service_variation_id | Read/write | Read/write | |
team_member_id | Read/write | Read/write | |
service_variation_version | Read/write | Read/write | |
any_team_member | Read-only | Read-only | |
intermission_minutes | None | Read-only | |
resource_ids | None | Read-only |
[*] When set, the value becomes immutable and cannot be updated with the specified permissions.
When booking a service, a booking application must choose a bookable business location for the scheduled appointment.
A business location is represented by a Location object and a booking is represented by a Booking object. To specify a business location for a booking, you reference the ID of the Location
object in the Booking
object.
To create and manage a booking, you need to supply the business location ID of a Square seller. To determine the location ID, you can call the ListLocations endpoint of the Locations API and present the result to the user to a location.
The following example shows how to call the ListLocations
endpoint in a cURL command:
List locations
{
"locations": [
{
"id": "EZDZF5AVRBXY4",
"name": "Default Test Account",
"address": {
"address_line_1": "1600 Pennsylvania Ave NW",
"locality": "Washington",
"administrative_district_level_1": "DC",
"postal_code": "20500",
"country": "US"
},
"timezone": "America/Los_Angeles",
"capabilities": [
"CREDIT_CARD_PROCESSING"
],
"status": "ACTIVE",
"created_at": "2020-04-15T00:26:32Z",
"merchant_id": "AM442MXDT6705",
"country": "US",
"language_code": "en-US",
"currency": "USD",
"phone_number": "+1 206-222-1111",
"business_name": "Mr. Mo's Hair",
"type": "PHYSICAL",
"business_hours": {
"periods": [
{
"day_of_week": "MON",
"start_local_time": "09:00:00",
"end_local_time": "17:00:00"
},
{
"day_of_week": "TUE",
"start_local_time": "09:00:00",
"end_local_time": "17:00:00"
},
{
"day_of_week": "WED",
"start_local_time": "09:00:00",
"end_local_time": "17:00:00"
},
{
"day_of_week": "THU",
"start_local_time": "09:00:00",
"end_local_time": "17:00:00"
},
{
"day_of_week": "FRI",
"start_local_time": "09:00:00",
"end_local_time": "17:00:00"
}
]
},
"business_email": "[email protected]",
"coordinates": {
"latitude": 38.897675,
"longitude": -77.036547
},
"mcc": "7299"
}
]
}
In this example, the seller runs the business at one location only. In addition to the business address, you can find the business hours in the result. Pay attention to the business hours so that you don't attempt to create a booking outside of the stated business hours.
When a seller has multiple business locations, the seller can enable some or all of the locations for bookings in an eligible subscription plan. This is done in the Square Dashboard by choosing Appointments, Settings, Manage Subscription, and Manage locations. Locations enabled this way become bookable in that the seller can create and manage bookings in the Square Dashboard or on a Square POS device.
For each bookable location, the seller can enable or disable online bookings for customers. Information about online bookings is encapsulated by the LocationBookingProfile and includes the URL of the location-specific online booking site.
When creating an application that supports online booking, you might want to find out which locations allow online booking so that your application presents only those locations for the user to choose from.
To determine whether a location is enabled for booking, call the ListLocationBookingProfiles endpoint without specifying any location IDs. To determine whether a bookable location is enabled for online booking, verify that the online_booking_enabled
field is set to true
on the returned LocationBookingProfile
object.
List location booking profiles
The response contains all bookable locations that might be enabled for online booking.
{
"location_booking_profiles": [
{
"location_id": "SNTR9180QMFGM",
"online_booking_enabled": true,
"booking_site_url": "https://broadway.squareup.com/book/SNTR9180QMFGM/acme-inc-schenectady-ny"
},
{
"location_id": "LHNSEA3K7RYSE",
"online_booking_enabled": false
}
],
"errors": []
}
Alternatively, you can call the RetrieveLocationBookingProfile endpoint with a specific location ID. If the specified location isn't bookable, the result is a 404
response containing the following error message:
{
"errors": [
{
"category": "INVALID_REQUEST_ERROR",
"code": "NOT_FOUND",
"detail": "This location either does not exists, or is not enabled for Bookings."
}
]
}
If the location is bookable but not enabled for online booking, the corresponding LocationBookingProfile
object containing "online_booking_enabled": false
is returned.
When creating a booking, you need to specify a team member as the service provider. You reference the team member by the team member ID.
Without specifying any team member IDs, you can retrieve booking profiles of team members by calling the ListTeamMemberBookingProfiles endpoint, as shown in the following example:
List team member booking profiles
{
"team_member_booking_profiles": [
{
"team_member_id": "pRNYL8gtKDFeFUtvC_Tz",
"display_name": "Sandbox Seller",
"is_bookable": true
}
],
"errors": []
}
Each bookable team member has a booking profile that has the is_bookable
attribute set to true
. Only bookable team members can be assigned to provide the service in a booking. A seller might have other employees as team members who aren't bookable for any service. These employees aren't included in the response.
Typically, you present the list of returned team members for the user to choose from to provide the service in a booking. When there is only one choice, simply make note of the returned team_member_id
value and provide this ID to a booking afterwards.
If team member IDs are readily accessible, you can retrieve the booking profiles of specific team members by calling the RetrieveTeamMemberBookingProfile or BulkRetrieveTeamMemberBookingProfiles endpoint and specifying the team member IDs.
To create a booking, you must specify a bookable service to be provided by the seller or one of the seller's team members. A bookable service is represented by a CatalogItemVariation object with its available_for_booking
attribute set to true
. To specify a bookable service, you reference the ID of the corresponding CatalogItemVariation
object.
To determine the ID of a bookable service, you can call the SearchCatalogItems endpoint, set the product_types
query expression to [APPOINTMENT_SERVICE]
, and inspect the result. The following example shows how to do this in cURL:
Search catalog items
{
"items": [
{
"type": "ITEM",
"id": "GU3K6H36IETW5BJXNUVQIITT",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_data": {
"name": "Hand Clean",
"description": "House cleaning service",
"variations": [
{
"type": "ITEM_VARIATION",
"id": "YW337JZR267JIALGVE5WWZR7",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "GU3K6H36IETW5BJXNUVQIITT",
"name": "Regular",
"ordinal": 1,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 8000,
"currency": "USD"
},
"service_duration": 7200000,
"available_for_booking": true,
"no_show_fee": {
"amount": 2500,
"currency": "USD"
},
"transition_time": 0
}
},
{
"type": "ITEM_VARIATION",
"id": "KRV4AOIPRWAMSBPBSSU2A2UW",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "GU3K6H36IETW5BJXNUVQIITT",
"name": "Power Clean",
"ordinal": 2,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 10000,
"currency": "USD"
},
"service_duration": 9000000,
"available_for_booking": true,
}
}
],
"product_type": "APPOINTMENTS_SERVICE",
"skip_modifier_screen": false
}
},
{
"type": "ITEM",
"id": "EC66KHZQFDXS2CUMBELGF2YK",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_data": {
"name": "Mr. Mo's Hair",
"description": "Hair styling for men and women",
"variations": [
{
"type": "ITEM_VARIATION",
"id": "RCTL5QBJIWUUDWGOX4YWOSNR",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "EC66KHZQFDXS2CUMBELGF2YK",
"name": "Men's hair cut",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 2500,
"currency": "USD"
},
"service_duration": 1800000,
"transition_time": 0
}
},
{
"type": "ITEM_VARIATION",
"id": "RHMBHQBSCELBY6LUR75OCK5H",
"updated_at": "2020-10-26T05:03:12.977Z",
"version": 1603688592977,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "EC66KHZQFDXS2CUMBELGF2YK",
"name": "Women's hair styling",
"ordinal": 1,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 10000,
"currency": "USD"
},
"service_duration": 7200000
}
}
],
"product_type": "APPOINTMENTS_SERVICE"
}
}
],
"matched_variation_ids": [
"YW337JZR267JIALGVE5WWZR7",
"KRV4AOIPRWAMSBPBSSU2A2UW",
"RCTL5QBJIWUUDWGOX4YWOSNR",
"RHMBHQBSCELBY6LUR75OCK5H"
]
}
Did you know?
In the previous response, the non-zero cancellation fee (as expressed by the no_show_fee
object) is set in the Square Dashboard. It cannot be set using the Bookings API. The service with a non-zero now_show_fee
value cannot be booked using the Bookings API.
You can infer the locations where the service is available from the present_at_all_locations
, present_at_locations_ids
, and absent_at_location_ids
attribute values of the returned services.
Make note of the ID and version number of the desired service item variation. You need to provide the ID when creating a booking afterwards. Don't use the ID of the parent item, as represented by a CatalogItem
object.
For a new bookable service, you must create a service variation, as represented by a CatalogItemVariation
instance embedded within a CatalogItem
object. You can do so in two ways:
- Using the Catalog API, you can call the UpsertCatalogObject or BatchUpsertCatalogObjects endpoint to create a service variation and set the
available_for_booking
attribute totrue
. - Using the Square Dashboard, you can create a bookable service variation by enabling the Bookable by Customers Online option for the newly created service.
To create a booking, you must specify a customer to receive the bookable service provided by the assigned or selected team member. In the Square API, a customer is represented by a Customer object. To specify a customer, you reference the ID of the Customer
object.
For a new customer, you can call the Customers API to create the customer, get the customer ID from the returned response, and specify the customer ID when creating a booking. The following example shows how to call the Customers API to create a new customer:
Create customer
When creating a customer to be used as an input to CreateBooking, the Customer object must have the phone_number
attribute defined.
{
"customer": {
"id": "5XSG36ZZ4WTF32XPGK0A7NZNMC",
"created_at": "2020-11-02T06:06:13.921Z",
"updated_at": "2020-11-02T06:06:13Z",
"given_name": "John",
"family_name": "Doe",
"email_address": "[email protected]",
"phone_number": "1234567890",
"preferences": {
"email_unsubscribed": false
},
"creation_source": "THIRD_PARTY",
"version": 0
}
}
Make note of the customer ID from the response. You need to supply it when creating a booking.
For an existing customer, you can call the SearchCustomers or ListCustomers endpoint of the Customers API to search for or retrieve the customer profile. The following cURL example shows how to call the SearchCustomers
endpoint to find the ID of the customer whose email address is [email protected]
:
Search customers
{
"customers": [
{
"id": "W3T65DYFQCXJXAW72Y677P5SW8",
"created_at": "2020-07-24T19:49:02.070Z",
"updated_at": "2020-07-24T19:49:02Z",
"given_name": "Joel",
"family_name": "Carpenter",
"email_address": "[email protected]",
"address": {
"address_line_1": "1234 major street E",
"administrative_district_level_1": "WA",
"postal_code": "98101",
"country": "US"
},
"phone_number": "2061112222",
"note": "not so private note",
"company_name": "ACME",
"preferences": {
"email_unsubscribed": false
},
"creation_source": "THIRD_PARTY",
"birthday": "2001-01-01T00:00:00-00:00",
"segment_ids": [
"AM442MXDT6705.REACHABLE",
"gv2:Q4N92Z69694EDDNFYFC2D2Q5KG"
],
"version": 3
}
]
}
Make note of the id
attribute value of the returned customer. You need to supply it when creating a booking.
You can use different search filters to select an existing customer by other supported attributes, including the name and phone number. For more information, see Search for Customer Profiles.
To determine how a Square seller accepts and manages bookings, you can call the RetrieveBusinessBookingProfile endpoint of the Bookings API to retrieve the business booking profile of the seller. The seller identity is inferred from the access token obtained using the OAuth API. For more information, see OAuth Walkthrough: Test Authorization with a Web Server.
The following cURL example retrieves a business booking profile:
Retrieve business booking profile
{
"business_booking_profile": {
"seller_id": "AM442MXDT6705",
"created_at": "2020-10-22T16:38:24Z",
"booking_enabled": true,
"customer_timezone_choice": "CUSTOMER_CHOICE",
"booking_policy": "ACCEPT_ALL",
"allow_user_cancel": true,
"business_appointment_settings": {
"location_types": [
"BUSINESS_LOCATION"
],
"alignment_time": "HALF_HOURLY",
"min_booking_lead_time_seconds": 0,
"max_booking_lead_time_seconds": 31536000,
"any_team_member_booking_enabled": true,
"multiple_service_booking_enabled": true,
"cancellation_fee_money": {
"currency": "USD"
},
"cancellation_policy": "CUSTOM_POLICY",
"skip_booking_flow_staff_selection": false
}
},
"errors": []
}
By inspecting the returned business booking profile, you can determine the booking policy for the business concerning, for example, whether the seller accepts booking requests automatically, whether multiple bookings are allowed, the booking's lead time, whether the customer can cancel a booking, and whether the customer can choose a team member.