# How to Integrate Retool with Acuity Scheduling

- Tool: Retool
- Difficulty: Beginner
- Time required: 15 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Acuity Scheduling using a REST API Resource with Basic authentication (User ID and API key). Configure the base URL once in the Resources tab, then build visual queries to manage appointments, calendars, and clients. The setup takes about 15 minutes and lets your team manage bookings faster than Acuity's native interface.

## Why Connect Retool to Acuity Scheduling?

Acuity Scheduling's client-facing booking page is polished, but the admin interface is optimized for single-user or small-team management rather than the operational demands of a busy reception desk, multi-location clinic, or high-volume service business. When your team needs to view all appointments across multiple calendars simultaneously, filter bookings by appointment type or staff member, or batch-cancel appointments due to an emergency closure, the native Acuity admin quickly shows its limits. A Retool app built over Acuity's API gives your operations team a customized interface that matches their specific workflow.

Acuity's API provides full CRUD access to appointments, calendars, appointment types, and client records. This means you can build a receptionist dashboard that shows the day's full schedule in a single table view, sorted by time and color-coded by appointment type — something Acuity's native calendar view cannot provide in a compact, actionable format. You can also combine Acuity appointment data with records from your internal database, CRM, or billing system to give staff a 360-degree view of each client without switching between applications.

For businesses with complex scheduling needs — multiple staff members, varied appointment types, and intake form data — the Retool integration also opens the door to building management dashboards that track booking rates, cancellation patterns, and staff utilization across time periods, using Chart components powered by Acuity's appointment data.

## Before you start

- A Retool account (Cloud or self-hosted) with permission to add Resources
- An Acuity Scheduling account on a plan that includes API access (Emerging Entrepreneur plan or higher)
- Your Acuity User ID and API key (found in Acuity at Business Settings → Integrations → API → Credentials)
- Basic familiarity with the Retool app builder and the query editor

## Step-by-step guide

### 1. Add an Acuity Scheduling REST API Resource

Navigate to the Resources tab in Retool by clicking Resources in the left sidebar on the home page, or via the top navigation. Click the blue Add Resource button in the upper right. In the resource type selector, search for 'REST' and click REST API to open the configuration form.

Fill in the resource details:
- Name: Enter 'Acuity Scheduling API' to clearly identify this resource.
- Base URL: Enter https://acuityscheduling.com/api/v1 — this is the base URL for all Acuity API endpoints.

For authentication, Acuity uses HTTP Basic auth. In the Authentication section, select Basic Auth from the dropdown. Enter your Acuity credentials:
- Username: Your Acuity User ID (a numeric string visible in Business Settings → Integrations → API)
- Password: Your Acuity API key (the alphanumeric key from the same settings page)

Rather than hardcoding these, store them as secret configuration variables first. Navigate to Settings → Configuration Variables in another tab, create ACUITY_USER_ID and ACUITY_API_KEY as secret variables. Then return to the resource configuration and enter:
- Username: {{ retoolContext.configVars.ACUITY_USER_ID }}
- Password: {{ retoolContext.configVars.ACUITY_API_KEY }}

Add a default Header: Content-Type: application/json. Click Save. The Acuity resource now appears in your Resources list.

**Expected result:** An Acuity Scheduling API resource appears in your Resources list. The User ID and API key are stored as secret configuration variables and referenced in the resource's Basic Auth fields.

### 2. Query today's appointments and display them in a Table

Create your first query to fetch appointments from Acuity. In your Retool app, click + New in the query panel. Select your Acuity Scheduling API resource. Set the HTTP Method to GET and the path to /appointments.

In the URL Parameters section, add parameters to filter appointments by date:
- minDate: {{ dateInput.value ? new Date(dateInput.value).toISOString().split('T')[0] : new Date().toISOString().split('T')[0] }} — this defaults to today if no date is selected
- maxDate: {{ dateInput.value ? new Date(dateInput.value).toISOString().split('T')[0] : new Date().toISOString().split('T')[0] }}
- max: 100 — limit results to prevent oversized responses

To filter by specific calendars, add the calendarID parameter: {{ calendarSelect.value || '' }}. To filter by appointment type, add appointmentTypeID: {{ typeSelect.value || '' }}.

Set the query to Run this query automatically when inputs change and trigger On page load. Add a JavaScript transformer to reshape the response.

Drag a Table component onto the canvas. Set its Data source to {{ appointmentsQuery.data }}. Configure columns: time (formatted), client name, appointment type, calendar/staff name, duration, and status. Add a DatePicker component above the Table labeled 'View date' — when the date changes, the query re-runs. Also add Select components for calendar and appointment type filters that will be populated by separate queries in the next step.

```
// JavaScript transformer to reshape Acuity appointments
const appts = Array.isArray(data) ? data : [];
return appts
  .sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
  .map(appt => ({
    id: appt.id,
    time: new Date(appt.datetime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
    date: new Date(appt.datetime).toLocaleDateString(),
    client_name: `${appt.firstName || ''} ${appt.lastName || ''}`.trim(),
    client_email: appt.email || '',
    client_phone: appt.phone || '',
    appointment_type: appt.type,
    duration_min: appt.duration,
    calendar: appt.calendar,
    calendar_id: appt.calendarID,
    status: appt.canceled ? 'Cancelled' : 'Scheduled',
    notes: appt.notes || ''
  }));
```

**Expected result:** The Table displays all appointments for the selected date, sorted chronologically with client names, appointment types, staff calendars, and statuses. Changing the date in the DatePicker re-fetches and updates the table automatically.

### 3. Load calendars and appointment types into filter dropdowns

To make your appointment table filters useful, populate the calendar and appointment type Select components with real data from Acuity rather than hard-coded values that would become outdated as your business changes.

Create a new query using your Acuity API resource. Set the method to GET and path to /calendars. This returns all staff calendars in your Acuity account. Set the trigger to On page load. Add a JavaScript transformer to extract just the ID and name fields into a clean array of { value, label } objects.

Create a second query, GET /appointment-types. Set it to trigger On page load as well. Apply a transformer to format the results as { value: type.id, label: type.name } objects.

Now configure the Select components in your app:
- For the calendar Select: set the Data source to {{ calendarsQuery.data }}, set Value field to 'value', and Label field to 'label'. Add an 'All calendars' option by enabling the Placeholder option in the Inspector.
- For the appointment type Select: set the Data source to {{ typesQuery.data }}, set Value field to 'value', and Label field to 'label'. Add an 'All types' placeholder.

When staff members are added or appointment types are created in Acuity, the filter dropdowns in your Retool app will automatically reflect those changes on the next page load — no manual updates required.

```
// JavaScript transformer for calendars query
// Apply to the /calendars GET query
const calendars = Array.isArray(data) ? data : [];
return calendars.map(cal => ({
  value: cal.id,
  label: cal.name,
  email: cal.email || '',
  timezone: cal.timezone || ''
}));
```

**Expected result:** The Calendar and Appointment Type Select components show the real names from Acuity, populated from the API. Selecting a filter value re-runs the appointments query and filters the table to that calendar or appointment type.

### 4. Add appointment cancellation and notes update capabilities

Build the ability to cancel appointments directly from your Retool dashboard. When a client calls to cancel, the receptionist should be able to select the appointment row and cancel it without leaving the tool.

Drag a Button component onto the canvas and label it 'Cancel Appointment'. In the Inspector, enable Confirm before running and set the confirmation message: 'Cancel appointment for {{ appointmentsTable.selectedRow.client_name }} at {{ appointmentsTable.selectedRow.time }}? This will notify the client by email.' This prevents accidental cancellations.

Create a new query using the Acuity API resource:
- Method: PUT
- Path: /appointments/{{ appointmentsTable.selectedRow.id }}/cancel
- Body: { 'notes': '{{ cancelReasonInput.value || 'Cancelled by staff' }}'}

Add a TextInput component labeled 'Cancellation reason' that the receptionist fills in before clicking Cancel. Reference this input in the query body so the reason is recorded in Acuity's notes field.

In the Cancel button's event handlers:
1. On Click: Trigger the cancel query
2. Add a second event handler: Action = Show notification, Message = 'Appointment cancelled. Client notification sent.'
3. Trigger the appointments query to refresh the table

Also add a separate TextArea component for updating appointment notes. Create a second PUT query: PUT /appointments/{{ appointmentsTable.selectedRow.id }} with body { 'notes': '{{ notesInput.value }}'} and a 'Save Notes' button that triggers it. This lets staff add follow-up notes to appointments that remain in Acuity's record.

```
{
  "notes": "{{ cancelReasonInput.value || 'Cancelled by staff at reception' }}"
}
```

**Expected result:** Selecting an appointment row and clicking Cancel Appointment shows a confirmation modal with the client's name and appointment time. After confirming, the appointment is cancelled in Acuity, the client receives an automated notification, and the table refreshes showing the updated status.

### 5. Build a new appointment booking form

Complete the receptionist dashboard by adding the ability to book new appointments for clients who call in. This requires three pieces of data: the appointment type, the calendar (staff member), and the client's information.

First, create a query to check available times. GET /availability/times requires the appointmentTypeID, calendarID, and date parameters. Reference Select components in the app for the appointment type and calendar selections, and a DatePicker for the requested date. Apply a transformer to format the available time slots as human-readable options.

Drag a Select component onto the canvas labeled 'Available times'. Set its data source to {{ availabilityQuery.data }} and configure label and value fields to show formatted time strings. When the staff member, appointment type, or date changes, the available times query re-runs and updates this dropdown automatically.

Drag a Form component (or group of TextInput components) onto the canvas for client details:
- First Name (TextInput)
- Last Name (TextInput)
- Email (TextInput with email validation)
- Phone (TextInput)
- Notes (TextArea)

Create a POST query to book the appointment: POST /appointments with a JSON body that maps the form inputs and selected time to Acuity's required fields. The key fields are datetime (from the selected available time slot), appointmentTypeID, calendarID, firstName, lastName, email, and phone.

Add a 'Book Appointment' button that triggers the POST query. In the success handler, show a notification ('Appointment booked for {{ firstName.value }} at {{ timeSelect.value }}'), clear the form fields, and refresh the appointments table.

```
{
  "appointmentTypeID": {{ typeSelect.value }},
  "calendarID": {{ calendarSelect.value }},
  "datetime": "{{ timeSelect.value }}",
  "firstName": "{{ firstNameInput.value }}",
  "lastName": "{{ lastNameInput.value }}",
  "email": "{{ emailInput.value }}",
  "phone": "{{ phoneInput.value }}",
  "notes": "{{ notesInput.value || '' }}"
}
```

**Expected result:** Selecting a staff member, appointment type, and date populates the available times dropdown with slots from Acuity. Filling in the client details form and clicking Book Appointment creates the appointment in Acuity and updates the day's schedule table.

## Best practices

- Store your Acuity User ID and API key as secret configuration variables in Retool Settings rather than entering them directly in the resource configuration form, which could expose them in audit logs.
- Always use confirmation modals before cancelling appointments — cancellation triggers an automatic client email notification and cannot be easily reversed.
- Cache the calendars and appointment-types queries (1-hour TTL) since staff members and service offerings change rarely, reducing unnecessary API calls throughout the workday.
- Format appointment datetimes using the client's local timezone in JavaScript transformers rather than UTC — use a timezone conversion utility or reference the calendar's timezone from the calendars query response.
- Add form validation on the booking form inputs (required fields, email format) using Retool's built-in input validation options before the POST query fires, to avoid failed API calls with missing required fields.
- Use Retool permission groups to restrict appointment cancellation and booking capabilities to designated staff roles — view-only access for read-only dashboards, full access for reception and management roles.
- Build a separate Retool Workflow with a Schedule trigger to send daily appointment summaries to your team's Slack channel, using Acuity's appointments API to fetch tomorrow's schedule each evening.
- Log all appointment cancellations and bookings to an internal database table with the Retool user's email and timestamp, creating an operations audit trail separate from Acuity's own records.

## Use cases

### Build a daily appointment management dashboard

Create a Retool panel that shows all appointments for today (or a selected date range) across all calendars. Reception staff can see client names, appointment types, times, status (scheduled, cancelled, no-show), and intake form answers in a single table. Clicking a row shows full appointment details in a side panel, and buttons allow cancellation or rescheduling without leaving the Retool interface.

Prompt example:

```
Build a daily appointment dashboard that fetches today's Acuity appointments sorted by time. Show client name, appointment type, start time, end time, calendar (staff member), and status in a Table. Add a Cancel button and a Reschedule button for the selected row. Include a date picker so staff can view any day's schedule.
```

### Create a multi-staff availability and booking panel

Build a Retool tool that shows available time slots across multiple staff calendars for a selected date and appointment type. Operations managers can view all staff availability side-by-side and manually book appointments on behalf of clients who call in. The panel shows each calendar's open slots and allows booking with client name, email, and phone number entered in a form.

Prompt example:

```
Create an availability panel that queries Acuity available times for a selected date, appointment type, and calendar. Display available slots in a list grouped by staff member. Add a booking form with fields for client name, email, and phone number that creates a new appointment when submitted.
```

### Build a no-show and cancellation analytics dashboard

Create a management reporting panel that queries Acuity appointments over a selected time range and calculates no-show rates, cancellation reasons, and peak booking times. Display the data in Charts and summary metrics using Retool's Chart and Stat components. Managers can filter by appointment type, staff member, and time period to identify patterns and optimize scheduling policies.

Prompt example:

```
Build an analytics panel that fetches Acuity appointments for a selected date range and calculates total bookings, cancellation count, cancellation rate, and no-show count. Show a bar chart of bookings by day, a pie chart of appointment types, and a table of cancellation reasons. Allow filtering by calendar (staff member) and appointment type.
```

## Troubleshooting

### All API requests return 401 Unauthorized even though the credentials look correct

Cause: Acuity uses HTTP Basic authentication where the User ID and API key are Base64-encoded together. If the Basic Auth fields are populated with the wrong values — for example, the API key placed in the username field or the User ID in the password field — all requests will fail with 401.

Solution: In the Retool Resources tab, click your Acuity resource and verify: Username must be your numeric Acuity User ID (not your email address, not your account name), and Password must be your API key (the long alphanumeric string from Acuity → Business Settings → Integrations → API). These are both visible on the same Acuity settings page — double-check that you have copied each value to the correct field.

### Appointments query returns an empty array even though appointments exist for the selected date

Cause: The minDate and maxDate parameters must be formatted as YYYY-MM-DD date strings matching Acuity's expected format. If you are passing a full ISO datetime string with timezone information (e.g., 2026-04-23T00:00:00.000Z), Acuity may reject or misinterpret the filter and return no results.

Solution: Format the date parameters explicitly in your URL parameter expressions: {{ new Date(dateInput.value).toISOString().split('T')[0] }}. This extracts just the YYYY-MM-DD portion. Also verify that the date you are filtering is not in the past if your Acuity account is configured to hide past appointments via certain plan settings.

```
// Correct date format for Acuity URL parameters
new Date(dateInput.value).toISOString().split('T')[0]
```

### Availability query returns an empty array even though the calendar has open time slots

Cause: The /availability/times endpoint requires both appointmentTypeID and calendarID as integer values, and the date must be a future date. If either parameter is missing, null, or passed as a string (e.g., '123' instead of 123), Acuity returns an empty array without an error message.

Solution: Wrap the Select component values in parseInt() in your URL parameter expressions: parseInt(typeSelect.value) and parseInt(calendarSelect.value). Also ensure the DatePicker value is for today or a future date — Acuity does not return availability for past dates. If the calendar has no availability configured for that day of the week, the response will also be empty.

### POST appointment creation fails with 'The selected time is no longer available'

Cause: Between the time the availability was queried and the time the booking form was submitted, another booking was made for that same slot. Acuity enforces real-time availability at the moment of booking, so slots that appeared available when the form was loaded may no longer be available by the time the POST is sent.

Solution: After the booking failure, add an On failure event handler that automatically re-runs the availability query to refresh the time slots, clears the selected time in the dropdown, and shows a notification: 'That time slot was just booked. Please select another available time.' This gives the receptionist immediate feedback and fresh availability data to select from.

## Frequently asked questions

### Does Acuity Scheduling have a native Retool connector or does it require a REST API Resource?

Acuity Scheduling does not have a native Retool connector with pre-built action dropdowns. You connect using a generic REST API Resource configured with Basic authentication (your Acuity User ID and API key). Despite requiring manual setup, the REST API Resource approach gives you access to all Acuity API endpoints including appointments, calendars, availability, appointment types, and client records.

### Can Retool be used to book appointments on behalf of clients who call in?

Yes. Create a booking form in Retool using TextInput components for client details (name, email, phone) and Select components for appointment type, calendar, and available time. Query Acuity's /availability/times endpoint to populate the time slot dropdown dynamically. When the form is submitted, a POST query to /appointments creates the booking in Acuity and triggers the client's confirmation email automatically.

### How do I display appointments across multiple staff calendars in a single Retool view?

Query the Acuity /appointments endpoint without specifying a calendarID to retrieve all appointments across all calendars simultaneously. Acuity returns a single flat array with a calendar field on each appointment indicating which staff member's calendar it belongs to. Add a color-coded badge or conditional row color in the Retool Table based on the calendar name to visually distinguish appointments by staff member.

### Can Retool receive Acuity webhook notifications for new bookings?

Yes. Create a Retool Workflow with a Webhook trigger to receive Acuity Scheduling notifications. The Workflow generates a public HTTPS endpoint URL that you enter in Acuity's settings under Business Settings → Integrations → Scheduling Page Embed & API → Developer. Acuity can send webhook events for new appointments, cancellations, and rescheduling — the Workflow receives the payload and can update your internal database, send Slack notifications, or log records.

### What Acuity plan do I need to access the API for Retool integrations?

Acuity Scheduling requires the Emerging Entrepreneur plan or higher to access the API. The Growing Business and Powerhouse Player plans also include API access. The free Freebie plan does not include API access. Once you are on an eligible plan, your User ID and API key are visible in Business Settings → Integrations → API → Credentials.

---

Source: https://www.rapidevelopers.com/retool-integrations/acuity-scheduling
© RapidDev — https://www.rapidevelopers.com/retool-integrations/acuity-scheduling
