Skip to main content
RapidDev - Software Development Agency
flutterflow-integrationsFlutterFlow API Call

Acuity Scheduling

Connect FlutterFlow to Acuity Scheduling using a FlutterFlow API Call with HTTP Basic authentication. Create an API Group pointed at acuityscheduling.com/api/v1, add a Base64-encoded Authorization header using your User ID and API key from Acuity Business Settings, then bind GET /appointments responses to a ListView. Note: API access requires the Emerging Entrepreneur plan or higher.

What you'll learn

  • How to locate your Acuity User ID and API key (they're not the same as your login credentials)
  • How to create a Base64-encoded Basic auth header and store it safely as an App Constant
  • How to set up an API Group in FlutterFlow and bind GET /appointments to a ListView
  • Why booking creation (POST /appointments) must go through a Firebase Cloud Function to protect your write credential
  • How to handle CORS on published web builds of your FlutterFlow app
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read45 minutesProductivityLast updated July 2026RapidDev Engineering Team
TL;DR

Connect FlutterFlow to Acuity Scheduling using a FlutterFlow API Call with HTTP Basic authentication. Create an API Group pointed at acuityscheduling.com/api/v1, add a Base64-encoded Authorization header using your User ID and API key from Acuity Business Settings, then bind GET /appointments responses to a ListView. Note: API access requires the Emerging Entrepreneur plan or higher.

Quick facts about this guide
FactValue
ToolAcuity Scheduling
CategoryProductivity
MethodFlutterFlow API Call
DifficultyIntermediate
Time required45 minutes
Last updatedJuly 2026

Add Appointment Booking to Your FlutterFlow App with Acuity Scheduling

Acuity Scheduling powers appointment booking for salons, coaches, clinics, and consultants worldwide. Its REST API (v1) lets your FlutterFlow app display upcoming bookings, check calendar availability, and create appointments on behalf of clients — turning a static calendar into a live in-app booking experience. The integration is particularly valuable for founders building a client-facing mobile app where scheduling is a core flow.

Before you start, check your Acuity plan: API access is only available on the Emerging Entrepreneur plan and above. Founders on the Personal or free plan will receive 403 errors regardless of their credentials. If you need API access, you'll need to upgrade first.

Acuity uses HTTP Basic authentication, which means every request carries a Base64-encoded string made from your User ID plus your API key. The important detail: the User ID is a numeric identifier found in Acuity's Business Settings → Integrations → API — it is NOT your email address. FlutterFlow doesn't have a built-in Basic auth helper, so you'll pre-compute the Base64 value, store it as an App Constant, and insert it into an Authorization header at the API Group level so every child call inherits it automatically.

Integration method

FlutterFlow API Call

FlutterFlow connects to Acuity Scheduling via its REST API (v1) using HTTP Basic authentication. You configure an API Group with the base URL and a shared Authorization header containing your Base64-encoded User ID and API key. Child API Calls within the group inherit the auth header and can fetch appointments, calendars, and client data to display in your app.

Prerequisites

  • An Acuity Scheduling account on the Emerging Entrepreneur plan or higher (required for API access)
  • Your Acuity User ID and API key from Business Settings → Integrations → API → Credentials
  • A FlutterFlow project (any plan) with the API Calls panel available
  • A Firebase project if you want to handle appointment creation securely via Cloud Functions
  • Basic familiarity with Base64 encoding (you can use any online Base64 encoder)

Step-by-step guide

1

Retrieve your Acuity User ID and API key

Log in to your Acuity Scheduling account and navigate to Business Settings (top-right menu) → Integrations → API. On the API page you will see two values: your User ID (a numeric string like 12345678) and your API key (a long alphanumeric string). Copy both of them to a safe place — you'll need them in the next step. A common mistake here: founders try to use their Acuity login email as the User ID. The User ID is a separate numeric identifier that only appears on this API credentials page. Using your email as the User ID will always result in a 401 Unauthorized error, so double-check that you're copying the numeric value. Also confirm your plan tier on this page. If you see a message indicating that API access is not available on your current plan, you will need to upgrade to Emerging Entrepreneur or higher before proceeding. Free-plan accounts receive 403 Forbidden responses from the API regardless of credentials.

Pro tip: The User ID is numeric (e.g., 12345678), not your email. If you paste your email as the User ID, you'll get 401 errors.

Expected result: You have your numeric Acuity User ID and your API key copied and ready to use.

2

Create the Base64 auth string and store it as an App Constant

Acuity's API uses HTTP Basic authentication. The Authorization header value is computed by Base64-encoding the string userId:apiKey (with a colon separator and no spaces). For example, if your User ID is 12345678 and your API key is abc123xyz, you Base64-encode the string 12345678:abc123xyz to get a result like MTIzNDU2Nzg6YWJjMTIzeHl6. To generate the Base64 value, open any online Base64 encoder (search for 'base64 encode online'), paste userId:apiKey into the input, and copy the output. The full Authorization header value will be: Basic MTIzNDU2Nzg6YWJjMTIzeHl6 (with the word 'Basic' and a space before the encoded string). In FlutterFlow, open your project and click the Settings icon in the left sidebar → App Values (App Constants). Click Add Constant, name it ACUITY_AUTH, set the type to String, and paste the full header value (including the word 'Basic'). FlutterFlow will bake this value into the compiled app, which is acceptable for read-only GET calls. For write operations (POST /appointments) you will protect the credential differently in a later step.

Pro tip: Include the word 'Basic ' (with a trailing space) when you store the constant, so you can reference it directly in the Authorization header without modification.

Expected result: An App Constant named ACUITY_AUTH containing the full Authorization header value is saved in your FlutterFlow project.

3

Create the Acuity API Group with the shared auth header

In FlutterFlow, click API Calls in the left navigation sidebar. You'll see a panel listing any existing API Groups. Click the + Add button and choose Create API Group. Give the group a name like AcuityScheduling. Set the Base URL to https://acuityscheduling.com/api/v1 — no trailing slash. This base URL will be shared by all API calls in the group, so you only configure it once. Now add the Authorization header. In the API Group settings, scroll to the Headers section and click Add Header. Set the key to Authorization and the value to {{ACUITY_AUTH}} — the double curly braces tell FlutterFlow to substitute the App Constant you created in the previous step. Every child API call inside this group will automatically inherit this header, so you don't need to repeat it per call. Also add a second header: Content-Type with value application/json. This ensures Acuity processes POST request bodies correctly in a later step. Save the API Group. You won't see any calls inside it yet — you'll add those next.

api_group_config.txt
1// API Group configuration reference
2// Base URL: https://acuityscheduling.com/api/v1
3// Headers (group-level, inherited by all child calls):
4// Authorization: {{ACUITY_AUTH}} (Basic Base64(userId:apiKey))
5// Content-Type: application/json

Pro tip: Set the Authorization header at the API Group level, not on individual calls. That way, if you need to rotate your API key, you update one App Constant and all calls pick up the change automatically.

Expected result: An AcuityScheduling API Group appears in the API Calls panel with the base URL and Authorization header configured.

4

Add the GET /appointments call and test the response

Inside the AcuityScheduling API Group, click Add API Call. Name it GetAppointments. Set the method to GET and the endpoint path to /appointments. Leave the path as-is — the base URL from the group will be prepended automatically. To filter appointments by date, add a query parameter. Click the Variables tab inside the API Call editor. Add a variable named minDate with type String and a default value of the current date in the format YYYY-MM-DD (e.g., 2026-07-10). Add another variable maxDate similarly. Back in the endpoint field, update the path to /appointments?minDate={{minDate}}&maxDate={{maxDate}} so FlutterFlow substitutes the variables when the call fires. Now click the Response & Test tab. Paste a sample Acuity appointments JSON response into the Sample Response field. A typical appointment object looks like: { "id": 1234, "firstName": "Jane", "lastName": "Doe", "email": "jane@example.com", "datetime": "2026-07-10T09:00:00-0700", "type": "Haircut" }. Click Generate from Response — FlutterFlow will auto-generate JSON Paths for each field. Now click the Test API Call button. If you've connected your real credentials correctly, you should see your actual upcoming appointments in the response panel. If you see a 403 error, your Acuity plan doesn't include API access. If you see a 401, double-check your Base64-encoded auth string.

appointments_response.json
1// Sample Acuity /appointments response (paste into Response & Test)
2[
3 {
4 "id": 1234567,
5 "firstName": "Jane",
6 "lastName": "Doe",
7 "email": "jane@example.com",
8 "phone": "+15551234567",
9 "datetime": "2026-07-10T09:00:00-0700",
10 "endTime": "2026-07-10T10:00:00-0700",
11 "type": "Haircut",
12 "calendar": "Main Location",
13 "calendarID": 1000001,
14 "notes": "First-time client",
15 "paid": "no",
16 "amountPaid": "0.00"
17 }
18]
19
20// Key JSON Paths to map:
21// Client name: $[*].firstName and $[*].lastName
22// Date/time: $[*].datetime
23// Service: $[*].type
24// Calendar: $[*].calendar
25// Appointment ID: $[*].id

Pro tip: Acuity returns appointments as a flat JSON array (not wrapped in an envelope), so your JSON Paths start with $[*] not $.data[*].

Expected result: The GetAppointments API Call returns a valid list of appointments in the Response & Test panel with JSON Paths generated for firstName, datetime, type, and other fields.

5

Bind the appointment list to a ListView widget

Navigate to the page in your FlutterFlow project where you want to show appointments (or create a new page). Add a ListView widget to the page canvas by clicking the + (Add Widget) button and searching for ListView. With the ListView selected, open the Backend Query panel on the right side. Set the Query Type to API Call, choose the AcuityScheduling group, and select GetAppointments. FlutterFlow will fetch this data when the page loads and pass the response items as children to the ListView. Inside the ListView, add a child widget (a Column or Card works well for each appointment row). Add Text widgets for the fields you want to display. For each Text widget, set the value using Set from Variable → API Response → GetAppointments → [the JSON Path for that field]. For example: - Client name: bind to $[*].firstName and $[*].lastName (combine them in a Text widget using string concatenation) - Date/time: bind to $[*].datetime (you may want a Custom Function to reformat the ISO datetime into a human-readable string like '10 Jul 2026, 9:00 AM') - Service type: bind to $[*].type Preview the page in Test Mode by clicking the Run button (top right). You should see your actual Acuity appointments listed. If the list is empty, check that you have appointments within the minDate/maxDate range you configured.

Pro tip: Add a Conditional Widget or Empty State widget below the ListView to handle the case when there are no upcoming appointments. This prevents the page from showing a blank screen.

Expected result: A scrollable ListView on the page shows each appointment with client name, datetime, and service type populated from the Acuity API response.

6

Route appointment creation through a Firebase Cloud Function

The GET /appointments call is read-only, and storing the auth credential in App Constants is acceptable for that use case. However, creating an appointment (POST /appointments) involves sending client personal information and writes data to Acuity using a write-capable API credential. If you include this call directly in FlutterFlow's client-side API Calls, the Base64 credential ships inside the compiled app and can be extracted by decompiling the APK or examining network traffic. The secure approach is to deploy a Firebase Cloud Function that holds the credential in server-side environment variables and proxies the booking request. Here's how to set it up: 1. In your Firebase project console, go to Functions → Write a new function (or use the Firebase Functions editor). Deploy a simple HTTPS callable function that accepts the appointment parameters, attaches the Authorization header server-side, and calls Acuity's POST /appointments on your behalf. 2. Back in FlutterFlow, create a new API Call (you can put it in a separate API Group if you prefer). Set the base URL to your Firebase Function URL (e.g., https://us-central1-your-project.cloudfunctions.net/createAcuityAppointment). This call has NO Authorization header — your FlutterFlow app just sends the appointment data and the Cloud Function handles the Acuity authentication. 3. In your booking form page (a Page with text fields for client name, email, and desired time), add an Action to the Submit button. Choose Backend/API Call → your Cloud Function proxy call. Pass the form field values as request body parameters. This pattern keeps your API credential fully server-side and also solves the CORS problem for web builds: browser-based FlutterFlow apps can't call acuityscheduling.com directly due to CORS restrictions, but they can call your Firebase Cloud Function which returns proper CORS headers.

index.js
1// Firebase Cloud Function: createAcuityAppointment/index.js
2const functions = require('firebase-functions');
3const fetch = require('node-fetch');
4
5exports.createAcuityAppointment = functions.https.onRequest(async (req, res) => {
6 // Set CORS headers for FlutterFlow web builds
7 res.set('Access-Control-Allow-Origin', '*');
8 res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
9 res.set('Access-Control-Allow-Headers', 'Content-Type');
10
11 if (req.method === 'OPTIONS') {
12 res.status(204).send('');
13 return;
14 }
15
16 const ACUITY_USER_ID = process.env.ACUITY_USER_ID;
17 const ACUITY_API_KEY = process.env.ACUITY_API_KEY;
18 const basicAuth = Buffer.from(`${ACUITY_USER_ID}:${ACUITY_API_KEY}`).toString('base64');
19
20 try {
21 const acuityResponse = await fetch(
22 'https://acuityscheduling.com/api/v1/appointments',
23 {
24 method: 'POST',
25 headers: {
26 'Authorization': `Basic ${basicAuth}`,
27 'Content-Type': 'application/json'
28 },
29 body: JSON.stringify(req.body)
30 }
31 );
32 const data = await acuityResponse.json();
33 res.status(acuityResponse.status).json(data);
34 } catch (error) {
35 res.status(500).json({ error: error.message });
36 }
37});
38
39// Set env vars in Firebase:
40// firebase functions:config:set acuity.user_id="YOUR_USER_ID" acuity.api_key="YOUR_API_KEY"

Pro tip: If you'd rather skip building and maintaining a Cloud Function, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

Expected result: A Firebase Cloud Function is deployed and accessible via HTTPS URL. Your FlutterFlow booking form submits appointments through the function, and the Acuity API key never appears in the client app bundle.

Common use cases

Salon booking app that shows upcoming client appointments

Build a mobile dashboard for salon staff where each team member can see their upcoming bookings for the day. The app fetches GET /appointments filtered by calendar ID and displays client name, service, and appointment time in a ListView. Staff can tap a booking to view client notes.

FlutterFlow Prompt

Show a list of today's appointments from Acuity Scheduling with client name, service type, and start time, sorted by time ascending.

Copy this prompt to try it in FlutterFlow

Coaching platform with in-app session scheduling

Let coaching clients browse available slots and book sessions directly inside a FlutterFlow mobile app. The app calls GET /availability to show open time slots and routes the booking creation POST through a Cloud Function so the API key is never exposed in the client bundle.

FlutterFlow Prompt

Display available appointment slots for the next 7 days and let users book a session by tapping a time slot, then confirm via email.

Copy this prompt to try it in FlutterFlow

Clinic reception app showing patient appointment queue

Build a front-desk companion app that displays the day's scheduled patients in order. The app polls GET /appointments with a date filter, shows patient name and appointment type in a scrollable list, and highlights appointments starting within the next 30 minutes.

FlutterFlow Prompt

Show a live queue of today's patient appointments from Acuity, refreshing every 5 minutes, with the next upcoming appointment highlighted.

Copy this prompt to try it in FlutterFlow

Troubleshooting

API returns 403 Forbidden even with valid credentials

Cause: Acuity's API is only available on the Emerging Entrepreneur plan or higher. Free and Personal plan accounts are not authorized to use the API regardless of credentials.

Solution: Log in to Acuity Scheduling → Business Settings → Integrations → API and confirm your plan tier. If the page shows an upgrade prompt rather than API credentials, upgrade your subscription before attempting any API calls.

401 Unauthorized — credentials are correct but auth fails

Cause: Either the Base64 encoding was computed incorrectly, or the User ID was entered as the email address rather than the numeric User ID found on the API credentials page.

Solution: Go to Business Settings → Integrations → API and copy the numeric User ID (not your email). Re-encode userId:apiKey (colon-separated, no spaces) using a Base64 encoder and update your ACUITY_AUTH App Constant in FlutterFlow. Make sure the constant value starts with 'Basic ' (the word Basic followed by a space).

XMLHttpRequest error on web build — works fine on mobile

Cause: Acuity Scheduling's API does not include Access-Control-Allow-Origin headers, which browsers require for cross-origin requests. Mobile Flutter builds bypass CORS enforcement; published web builds do not.

Solution: Route all API calls through a Firebase Cloud Function that sets proper CORS headers (see step 6). The FlutterFlow app calls the Cloud Function URL instead of acuityscheduling.com directly. This applies to both GET and POST calls when targeting web builds.

ListView shows no appointments even though they exist in Acuity

Cause: The minDate/maxDate query parameters may be filtering out your appointments, or the date format does not match what Acuity expects (YYYY-MM-DD in the ISO 8601 format with the timezone of your Acuity account).

Solution: Open the Response & Test tab in the GetAppointments API Call. Set minDate to a past date (e.g., one week ago) and maxDate to a date one month in the future, then click Test API Call to see if appointments return. If they do, your filtering parameters in the UI need adjustment. Also confirm you're looking at the correct calendar ID if you have multiple calendars.

Best practices

  • Store the Base64 auth string as an App Constant named ACUITY_AUTH rather than hardcoding it in individual API Call headers — if you need to rotate the key, update one constant and all calls pick up the change.
  • Always proxy POST /appointments (and any write operation) through a Firebase Cloud Function to prevent the API credential from being exposed in the compiled app bundle.
  • Use date range query parameters (minDate, maxDate) on GET /appointments to limit response size — fetching all historical appointments on every page load is wasteful and slow.
  • Cache appointment data in App State when navigating between pages so your app doesn't re-fetch the same appointments every time a user taps back.
  • Add an empty-state widget to your appointment ListView so users see a friendly message ('No upcoming appointments') rather than a blank screen when the date range returns zero results.
  • Test all API calls in FlutterFlow's Test Mode first before publishing to web — CORS issues only surface on published web builds, so identify them early by testing on device or checking the Cloud Function flow.
  • Handle the 403 response code explicitly in your app UI by showing a message like 'API access unavailable' rather than a generic error, to help you or your team diagnose plan-related issues quickly.

Alternatives

Frequently asked questions

Can I use Acuity Scheduling's API on the free plan?

No. Acuity's REST API is only available on the Emerging Entrepreneur plan and above. Free and Personal plan accounts will receive 403 Forbidden responses from every API endpoint, even with valid credentials. Check the Business Settings → Integrations → API page in your account to confirm your access level before building the integration.

Does FlutterFlow have a native Acuity Scheduling integration?

No. There is no native FlutterFlow connector for Acuity Scheduling. The integration is built manually using FlutterFlow's API Calls panel with an API Group configured for HTTP Basic authentication. This tutorial covers the full setup process including the API Group, auth header, response binding, and secure booking creation.

Why do I need a Firebase Cloud Function just to create bookings?

FlutterFlow compiles to a client-side Flutter app that runs on the user's device. Any API key or credential you put in the API Calls panel ships inside the compiled app binary, where it can be extracted by decompiling the APK. Since the Acuity API key has write access to all your booking data, you protect it by keeping it in a server-side Cloud Function instead. The FlutterFlow app calls the function, and the function calls Acuity with the real credential.

My app works in FlutterFlow's Test Mode but breaks when I publish to web — what's happening?

FlutterFlow's Test Mode proxies API calls through FlutterFlow's own servers, which bypasses browser CORS enforcement. When you publish to web, the browser enforces CORS and blocks direct calls to acuityscheduling.com because that domain doesn't return an Access-Control-Allow-Origin header. The fix is to route calls through a Firebase Cloud Function that adds CORS headers, as described in step 6.

How do I display appointment times in the user's local timezone?

Acuity returns datetime values in ISO 8601 format with a UTC offset (e.g., 2026-07-10T09:00:00-0700). In FlutterFlow, add a Custom Function (Custom Code → + Add → Function) that parses this string using Dart's DateTime.parse() method and formats it with the intl package using DateFormat. You can also display the datetime string as-is if your users are in a single timezone, or convert it using the user's device timezone via DateTime.now().timeZoneName.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire FlutterFlow integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.