Site logo

Acuity Scheduling – Sync FAQ & SOP

Acuity Scheduling Integration

Sync FAQ & Standard Operating Procedures
HiLucy Platform — KAN Hotel Wellness — February 2026
For: Operations, Development, and Business Stakeholders

Audience Guide:
Everyone All audiences  
Business Non-technical stakeholders  
Operations Hotel ops & administrators  
Developer Technical team

1 How the Integration Works Everyone

The Acuity Scheduling integration connects KAN Hotel’s wellness spa scheduling system (Acuity) to the HiLucy booking platform (WordPress + WooCommerce). This allows guests to browse, select time slots, and book wellness services directly through the HiLucy storefront — while Acuity remains the master scheduling system.

54
Appointment Types
in Acuity

9
Service Categories

8
Add-on Services

2
Calendars
(Spa & Programming)

The Two Systems at a Glance

Acuity Scheduling (Source)

  • Defines all services, classes, and pricing
  • Manages practitioner calendars
  • Controls real-time availability
  • Stores appointment records
  • Sends webhook events on changes

HiLucy / WordPress (Destination)

  • Displays services to guests
  • Shows live time slot availability
  • Handles Stripe payment checkout
  • Creates appointments in Acuity on order
  • Stores booking & payment records

High-Level Data Flow

Acuity
Scheduling
Catalog
Sync
WordPress
WC Products
Guest
Browses & Books
Appointment
Created in Acuity

2 Source of Truth & Sync Direction Everyone

Golden Rule: Acuity is the source of truth for all catalog data.
Prices, service names, durations, capacities, add-ons, and categories should always be edited in Acuity. Any changes made directly in WordPress will be overwritten on the next sync.

Sync Direction Summary

Data Direction Who Controls It
Service names & descriptions Acuity → WP Edit in Acuity
Prices (MXN) Acuity → WP Edit in Acuity
Durations Acuity → WP Edit in Acuity
Capacities (class sizes) Acuity → WP Edit in Acuity
Add-ons & pricing Acuity → WP Edit in Acuity
Categories Acuity → WP Edit in Acuity
Calendar/practitioner schedules Acuity → WP Edit in Acuity
Appointment creation (bookings) WP → Acuity Triggered by WP checkout
Cancel & reschedule events Acuity → WP Done in Acuity, synced via webhook
Staff assignments Not synced Managed separately in each system
Payment & Stripe data Not synced WooCommerce / Stripe only
Customer accounts Not synced Separate in each system
What happens if you edit a price in WordPress directly?
It will appear correct temporarily, but the next catalog sync will overwrite it with the Acuity price. Always change prices in Acuity first, then trigger a sync.

3 What Gets Synced (and What Doesn’t) Operations

Synced: Acuity → WordPress

Acuity Entity WordPress Storage Fields Synced
Calendars (practitioners/rooms) wp_acuity_calendars Name, email, description, location, thumbnail
Appointment Types (services/classes) wp_acuity_appointment_types Name, description, duration, price, currency, category, type, class size, calendar, color
Add-ons wp_acuity_products Name, description, price, currency
Packages / Certificates wp_acuity_products Name, description, price, currency

When product sync is enabled (--with-products), the data also flows into WooCommerce products:

Source (Acuity) Destination (WC Product Meta) Notes
Price (MXN) _activity_price / _price (USD) Auto-converted MXN → USD at 17.5 rate
Duration _activity_duration In minutes
Class size _activity_capacity Determines qty selector visibility
Category product_cat taxonomy Auto-created terms
Add-ons _activity_addons Serialized array per product

NOT Synced

These items are intentionally excluded from sync:

  • Staff assignments — WordPress staff model is separate from Acuity calendars
  • Customer data — Guest accounts are not shared between systems
  • Payment status — Stripe payments live in WP/Stripe only, Acuity has no visibility
  • Appointment status changes — Only cancel/reschedule events sync back; “confirmed” or “no-show” status stays in Acuity
  • WP product edits back to Acuity — Changing a product name in WordPress does NOT update Acuity

Sync Behavior: Upsert & Soft Delete

Every sync uses upsert logic: records are matched by (acuity_id, listing_id). Existing records are updated; new ones are inserted. Records that no longer exist in Acuity are soft-deleted (is_active = 0), never permanently removed. This preserves historical data and prevents broken references.

4 Sync Triggers & Update Schedule Operations

Webhook-triggered syncs now include WC product updates automatically.
There is no recurring cron job. Instead, every Acuity webhook event (booking, cancellation, reschedule) triggers a full sync that updates both catalog tables and WooCommerce products (prices, durations, capacities). Manual syncs are only needed for immediate updates when no booking activity has occurred.

The Four Sync Triggers

Trigger Who Uses It What It Does When to Use
1. Admin UI “Sync Now” Admins (wp-admin) Catalog sync via REST API Quick check after Acuity changes
2. WP-CLI Command DevOps / SSH access Full sync with optional WC product update Initial setup, bulk changes, troubleshooting
3. REST API Developers / automation Catalog sync via HTTP POST CI/CD pipelines, external scripts
4. Webhook (automatic) Acuity (event-driven) Full sync: catalog tables + WC product updates Every appointment event in Acuity

How Each Trigger Works

1. Admin UI — “Sync Now” Button

In wp-admin, open the listing edit screen (post type: job_listing). The Acuity Scheduling metabox on the right sidebar shows credentials, last sync time, and a “Sync Now” button. Clicking it fires a REST API call to POST /wp-json/hilucy/v1/listings/{id}/acuity/sync.

2. WP-CLI — Command Line

The most powerful trigger. Supports catalog-only or full WC product sync, type filtering, and dry-run mode.

# Catalog sync only (tables only, no WC products)
wp hilucy acuity-sync --listing=14216

# Full sync: catalog + create/update WC products
wp hilucy acuity-sync --listing=14216 --with-products

# Dry run: preview WC product changes without applying
wp hilucy acuity-sync --listing=14216 --with-products --dry-run

3. REST API — HTTP Endpoint

POST /wp-json/hilucy/v1/listings/14216/acuity/sync
# Requires: manage_options capability (admin-level auth)

4. Webhook — Automatic Event-Driven

When anything changes in Acuity (new appointment, cancellation, reschedule), Acuity sends a webhook to HiLucy. The webhook handler schedules a one-time async event using wp_schedule_single_event() that runs a full sync including WC product updates (prices, durations, capacities). This is not a recurring cron — it’s a single deferred action that runs once, usually within 1-2 minutes. This means price changes in Acuity are automatically reflected on the storefront.

Update Schedule Summary

Mechanism Frequency Scope
Recurring cron job None (not configured)
Webhook-triggered async sync Reactive (on every Acuity event) Catalog tables + WC products (full sync)
Availability cache TTL 15 minutes auto-expiry Slot data (transient cache)
Error cache TTL 5 minutes auto-expiry Failed API responses
Manual sync On-demand Catalog + optionally WC products
Tip: Webhook syncs are automatic but event-driven.
Price and catalog changes in Acuity are picked up automatically on the next webhook event (any booking activity). If you need changes reflected immediately and there’s no upcoming booking activity, run a manual sync: wp hilucy acuity-sync --listing=14216 --with-products

5 Webhooks — Real-Time Event Handling Operations Developer

Acuity sends real-time notifications (webhooks) to HiLucy whenever appointments change. These keep the WordPress booking records in sync without manual intervention.

Registered Webhook Events

Acuity Event Webhook ID What HiLucy Does
appointment.scheduled 909411 Logs event, clears availability cache, schedules full sync (catalog + WC products)
appointment.rescheduled 909412 Fetches new datetime, updates wp_bookings dates + order item meta
appointment.canceled 909413 Sets wp_bookings.status = 'cancelled' for matching order
appointment.changed 909414 Logs event, clears cache, schedules re-sync
order.completed 909415 Logs event, schedules re-sync

Webhook Endpoint

https://dev.hilucy.com/wp-json/hilucy/v1/acuity-webhook
# Public endpoint (no auth required — Acuity doesn't support signed webhooks)

How Webhook → WC Order Matching Works

1
Acuity sends appointment ID in webhook payload
2
HiLucy searches wp_woocommerce_order_itemmeta

Looks for _acuity_appointment_id = {id}

3
Finds matching WC order (if created from HiLucy)

If not found (appointment wasn’t from WooCommerce), webhook is logged but ignored

4
Updates wp_bookings record accordingly

Cancel → status=cancelled | Reschedule → new dates

Webhook Configuration in Acuity

To set up webhooks for a new environment, go to Acuity → Integrations → API → Webhooks and add the endpoint URL for each event type. The webhook URL is also displayed in the Acuity metabox within the WordPress listing editor.

Security Note: The webhook endpoint is public (permission_callback => '__return_true') because Acuity doesn’t support HMAC-signed webhooks. Security is maintained by only performing reads and updates against known appointment IDs — no destructive actions.

6 Booking Flow — End to End Everyone

This is the complete journey from a guest browsing a wellness service to the appointment being confirmed in Acuity.

1
Guest visits product page

Frontend detects Acuity-linked product via _acuity_appointment_type_id meta and fetches real-time availability from Acuity API

2
Guest selects a time slot

Day tabs show available dates. Guest clicks a slot button, optionally selects add-ons. For classes (capacity > 1), a quantity selector allows booking multiple spots.

3
Guest clicks “Reserve your spot”

Server-side validation: nonce check, event hasn’t started, spots still available, selected time still valid

4
Cart & Checkout

Cart stores time slot, add-ons, staff selection. Price calculated: base MXN → USD + add-on fees. Guest enters billing info and pays via Stripe.

5
Order completes — internal booking records

Hook priority 20: hilucy_push_bookings_to_tables() inserts records into wp_bookings and wp_service_requests

6
Acuity appointment creation

Hook priority 25: POST /appointments sent to Acuity API with appointment type, datetime, guest info, and selected add-on IDs. For classes with qty > 1, one appointment is created per unit.

7
Vendor notification

WhatsApp template message sent to the wellness spa staff

Key Safeguards

Scenario What Happens
Acuity appointment creation fails Error logged to _acuity_booking_error on order item. WC order still completes. Appointment must be created manually in Acuity.
Guest reloads thank-you page Flag _acuity_appointments_created prevents duplicate appointment creation
Time slot booked by someone else between selection and checkout Acuity API returns an error. Logged as booking error on the order.

7 Availability, Caching & Slot Display Operations

How Real-Time Availability Works

When a guest loads a product page for an Acuity-linked service, the system fetches live availability:

Product Page
Loads
Check Cache
(15 min TTL)
Acuity API
/availability/dates
Acuity API
/availability/times
Render
Slot UI

Cache Configuration

Cache Type Key Pattern TTL When Cleared
Available dates acuity_avail_{typeID}_{calID}_{YYYYMM} 15 minutes On webhook event, or auto-expiry
Time slots acuity_slots_{typeID}_{calID}_{YYYYMMDD} 15 minutes On webhook event, or auto-expiry
API errors (internal) 5 minutes Auto-expiry only

Availability Lookup Window

28
Days Ahead
(default lookahead)

48
Max Slots
(per calendar)

15 min
Cache TTL
(auto-refresh)

The frontend is identical for both Acuity-linked and manually-scheduled products.
The availability system returns the same data structure regardless of source. Staff cards, day tabs, and slot buttons render the same way.

8 Add-ons & Price Conversion Business Operations

How Add-ons Work

Add-ons are extra services guests can select when booking (e.g., “Aloe Vera Facial” with a Thai massage). They are defined in Acuity and synced to WordPress during catalog sync.

1
Acuity add-ons synced to wp_acuity_products

During Phase 1 catalog sync

2
Add-ons written to product meta (_activity_addons)

During Phase C sync (requires --with-products)

3
Guest sees checkboxes on product page

Each add-on shows name, duration, and price (USD with MXN equivalent)

4
Checked add-ons become WC fee line items at cart/checkout
5
Add-on IDs sent to Acuity in addonIDs[] when appointment is created

Per-Type Add-on Filtering

Not all add-ons apply to all services. For example, facial add-ons only apply to massages, not yoga classes. The addon map controls this:

Map Status Behavior
Add-on in the map Only shown on products matching the listed appointment type IDs
Add-on not in the map Treated as global — shown on all products
No map configured All add-ons shown on all products (backwards compatible)

MXN → USD Price Conversion

Acuity stores all prices in MXN. The WooCommerce store uses USD. The integration handles automatic conversion:

Conversion formula: USD Price = MXN Price ÷ Exchange Rate
Default rate: 17.5 (configurable via hilucy_mxn_usd_rate filter)

Example: MXN 2,200 massage → $125.71 USD | MXN 450 add-on → $25.71 USD
Display format: “$25.71 (MXN 450)”

9 Standard Operating Procedures Operations

SOP 1: Initial Setup for a New Listing

Prerequisites: Acuity account with API credentials, listing post created in WordPress, SSH access to the server.
1
Configure Acuity credentials on the listing

wp-admin → Listings → Edit listing → Acuity metabox → Enter User ID + API Key → Check “Enabled” → Save
Or via CLI:

wp post meta update 14216 _hilucy_acuity_user_id '38276424'
wp post meta update 14216 _hilucy_acuity_api_key 'your-api-key'
wp post meta update 14216 _hilucy_acuity_enabled 'yes'

2
Run catalog sync

wp hilucy acuity-sync --listing=14216
3
Preview WC product changes (dry run)

wp hilucy acuity-sync --listing=14216 --with-products --dry-run
4
Create WC products

wp hilucy acuity-sync --listing=14216 --with-products
5
Verify the sync

wp hilucy acuity-match --listing=14216
wp hilucy acuity-products --listing=14216
6
Configure webhooks in Acuity

Acuity → Integrations → API → Webhooks → Add URL for all 5 event types:
https://your-site.com/wp-json/hilucy/v1/acuity-webhook

7
(Optional) Set up per-type add-on filtering

wp hilucy acuity-addon-map --listing=14216 --seed

SOP 2: Update a Service Price

1
Change the price in Acuity

Acuity → Appointment Types → Select service → Edit price → Save

2
Wait for automatic sync (or trigger manually)

The next webhook event (any booking activity) will automatically sync the new price to WordPress. For immediate updates:

wp hilucy acuity-sync --listing=14216 --with-products

3
Verify

Check the product page on the storefront to confirm the new USD price (auto-converted from MXN)

Do NOT edit the price in WordPress. It will be overwritten on the next sync. Always change prices in Acuity first.

SOP 3: Add a New Service in Acuity

1
Create the appointment type in Acuity

Set name, duration, price (MXN), category, capacity (1 for service, >1 for class), and assign a calendar

2
Run a full sync with products

wp hilucy acuity-sync --listing=14216 --with-products

A new WC Activity product will be auto-created and linked to the Acuity type.

3
Verify the new product

wp hilucy acuity-products --listing=14216

Check the product appears in the storefront and shows availability.

SOP 4: Remove a Service

1
Delete or deactivate the appointment type in Acuity

Remove the calendar assignment to prevent bookings, or delete the type entirely

2
Run a sync

The type will be soft-deleted (is_active=0) in the wp_acuity_* tables. The WC product will be set to draft if the calendar was removed.

3
(Optional) Manually delete or hide the WC product in wp-admin

SOP 5: Deploy to a New Environment (STG/PRD)

  • Push plugin to target environment via CI/CD
  • Set Acuity credentials on the listing (wp post meta update)
  • Run initial catalog sync: wp hilucy acuity-sync --listing=14216
  • Run product sync: wp hilucy acuity-sync --listing=14216 --with-products
  • Update webhook URLs in Acuity to the target domain
  • Verify via wp hilucy acuity-list --listing=14216
  • Test a booking end-to-end with test data

SOP 6: Investigate a Failed Booking

1
Find the WC order in wp-admin → Orders
2
Check order item meta for _acuity_booking_error

This contains the error message from the Acuity API call

3
Check debug.log for detailed logging

Search for the order ID or “Acuity” around the order timestamp

4
Common causes

• Missing activity_start on order item (form data not saved)
• Time slot taken by another guest between selection and checkout
• Acuity API temporarily down or rate-limited

5
Create appointment manually in Acuity if needed

Use the guest’s booking details from the WC order

10 CLI & API Quick Reference Developer

WP-CLI Commands

Command Purpose
wp hilucy acuity-sync --listing=ID Catalog sync only (tables)
wp hilucy acuity-sync --listing=ID --with-products Catalog + WC product sync
wp hilucy acuity-sync --listing=ID --with-products --dry-run Preview product changes
wp hilucy acuity-sync --listing=ID --type=calendars Sync only calendars
wp hilucy acuity-sync --listing=ID --type=appointment-types Sync only appointment types
wp hilucy acuity-sync --listing=ID --type=products Sync only packages + add-ons
wp hilucy acuity-list --listing=ID Display all synced data
wp hilucy acuity-match --listing=ID Matching report: Acuity ↔ WC
wp hilucy acuity-products --listing=ID List Acuity-linked WC products
wp hilucy acuity-addon-map --listing=ID View add-on mapping
wp hilucy acuity-addon-map --listing=ID --seed Seed add-on mapping
wp hilucy acuity-addon-map --listing=ID --clear Clear add-on mapping

REST API Endpoints

Endpoint Method Auth Purpose
/hilucy/v1/listings/{id}/acuity/appointment-types GET Logged in List appointment types
/hilucy/v1/listings/{id}/acuity/calendars GET Logged in List calendars
/hilucy/v1/listings/{id}/acuity/products GET Logged in List packages/add-ons
/hilucy/v1/listings/{id}/acuity/sync POST Admin Trigger catalog sync
/hilucy/v1/acuity-webhook POST Public Receive Acuity events

Query Filters

Endpoint Filter Values
appointment-types ?category=Yoga Acuity category name
appointment-types ?type=class service or class
appointment-types, calendars, products ?active=1 1 (active) or 0 (deleted)
products ?product_type=addon addon or package

Database Tables

Table Purpose Key Columns
wp_acuity_calendars Practitioners / rooms acuity_id, listing_id, name, is_active
wp_acuity_appointment_types Services & classes acuity_id, listing_id, name, duration, price, type, class_size
wp_acuity_products Packages & add-ons acuity_id, listing_id, name, price, product_type

11 Troubleshooting Guide Operations Developer

Symptom Cause Fix
“Acuity credentials not configured for this listing” Missing _hilucy_acuity_user_id or _hilucy_acuity_api_key Check the Acuity metabox in listing editor. Re-enter credentials.
Sync returns 0 calendars / 0 types Bad credentials or empty Acuity account Test credentials in Acuity API explorer. Check debug.log for HTTP errors.
WC products not created after sync Used catalog-only sync Re-run with --with-products flag.
Product page shows “No openings in the next few days” No availability in Acuity calendar, or stale cache Check Acuity calendar settings. Wait 15 min for cache expiry or trigger a webhook event.
Product is in “draft” status Acuity type has no calendar assigned Assign a calendar in Acuity and re-sync. Product will auto-publish.
Appointment not created in Acuity after checkout Various (missing start date, API error) Check _acuity_booking_error on order item meta. Check debug.log.
Webhook events not updating bookings Webhook URL misconfigured or appointment not from WC Check Acuity webhook settings. Look for “Acuity webhook received” in debug.log.
Add-ons showing on wrong products Missing or incorrect addon map Check with wp hilucy acuity-addon-map --listing=ID. Use --seed to configure per-type filtering.
Price shows old value after Acuity change No webhook event has fired since the change Wait for next booking activity (auto-syncs) or run wp hilucy acuity-sync --listing=ID --with-products manually.
Name matching not working (duplicate product created) Name normalization mismatch (accents, dashes, entities) Check wp hilucy acuity-match --listing=ID for mismatches. May need manual linking.
Stale availability data after 15+ minutes Webhooks not clearing cache Verify webhooks are configured in Acuity. Transients expire after 15 min regardless.

12 Frequently Asked Questions Everyone

Where should I change prices — in Acuity or WordPress?
Always in Acuity. Acuity is the source of truth. Prices in WordPress are automatically updated when the next webhook fires (any booking activity). You can also trigger a manual sync if you need the change reflected immediately.

Is the sync bidirectional?
Partially. Catalog data (services, prices, add-ons) flows one-way: Acuity → WordPress. The only data that flows the other direction is appointment creation at checkout (WordPress → Acuity). Cancel/reschedule events flow back via webhook (Acuity → WordPress).

Is there an automatic daily sync?
No recurring cron, but syncs are automatic. Every Acuity webhook event (booking, cancellation, reschedule) triggers a full sync that updates both catalog tables and WooCommerce products. This keeps the storefront current without manual intervention. Manual syncs are only needed for immediate updates when no booking activity has occurred.

How quickly do availability changes show on the website?
Availability is cached for 15 minutes. When someone books in Acuity, a webhook fires that immediately clears the cache. The next page load fetches fresh data. Without webhooks, changes appear within 15 minutes.

What happens if I add a new service in Acuity?
A new WooCommerce product will be automatically created on the next webhook-triggered sync (any booking activity). The product will be linked to the Acuity type with the correct price (converted to USD), duration, and category. For immediate creation, run a manual sync: wp hilucy acuity-sync --listing=14216 --with-products.

What happens if I delete a service in Acuity?
On the next sync, the record is soft-deleted (is_active=0). If the calendar was also removed, the WC product is set to draft (hidden from the storefront). Existing bookings are not affected.

Can guests book a class for multiple people?
Yes. Classes (appointment types with capacity > 1) show a quantity selector on the product page. Each quantity unit creates a separate Acuity appointment. For example, booking qty 3 for a yoga class creates 3 individual appointments — and 3 spots are deducted from availability.

What if the Acuity appointment creation fails at checkout?
The WooCommerce order still completes (the guest gets their confirmation and is charged). The error is logged in _acuity_booking_error on the order item. An admin must then create the appointment manually in Acuity.

Can I cancel an appointment from WordPress?
Not currently. Cancellations should be made in Acuity. When you cancel in Acuity, a webhook fires that updates the WordPress booking record to “cancelled”. The reverse direction (WP → Acuity cancel) is not implemented.

Why are some products missing from the storefront?
Common reasons: (1) The Acuity type has no calendar assigned (product set to draft). (2) The sync was run without --with-products. (3) The product was manually trashed in wp-admin. Run wp hilucy acuity-products --listing=ID to check the status of all linked products.

How is the exchange rate managed?
The default MXN-to-USD rate is 17.5, hardcoded in the product class. Developers can override it with the hilucy_mxn_usd_rate filter. It is not automatically updated from external exchange rate APIs.

Are Acuity payments connected to Stripe in WordPress?
No. The two payment systems are completely separate. Guests pay through WooCommerce’s Stripe gateway. Acuity does not know about these payments. If Acuity is configured to accept payments directly, those are also separate.

Can I connect multiple Acuity accounts to different listings?
Yes. Each listing stores its own Acuity User ID and API Key. Different hotels or properties can each have their own Acuity account connected independently.

What’s the difference between “catalog sync” and “product sync”?
Catalog sync populates the three wp_acuity_* tables (raw data mirror of Acuity). Product sync (--with-products) additionally creates/updates WooCommerce Activity products that guests can actually browse and purchase. As of February 2026, webhook-triggered syncs automatically include both phases, so WC products are kept in sync without manual intervention.