Acuity Scheduling – Sync FAQ & SOP
Acuity Scheduling Integration
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.
in Acuity
(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
Scheduling
Sync
WC Products
Browses & Books
Created in Acuity
2 Source of Truth & Sync Direction Everyone
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 |
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
- 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
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 |
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
Acuity sends appointment ID in webhook payload
HiLucy searches
wp_woocommerce_order_itemmeta
_acuity_appointment_id = {id}Finds matching WC order (if created from HiLucy)
Updates
wp_bookings record accordingly
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.
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.
Guest visits product page
_acuity_appointment_type_id meta and fetches real-time availability from Acuity APIGuest selects a time slot
Guest clicks “Reserve your spot”
Cart & Checkout
Order completes — internal booking records
hilucy_push_bookings_to_tables() inserts records into wp_bookings and wp_service_requestsAcuity appointment creation
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.Vendor notification
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:
Loads
(15 min TTL)
/availability/dates
/availability/times
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
(default lookahead)
(per calendar)
(auto-refresh)
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.
Acuity add-ons synced to
wp_acuity_products
Add-ons written to product meta (
_activity_addons)
--with-products)Guest sees checkboxes on product page
Checked add-ons become WC fee line items at cart/checkout
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:
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
Configure Acuity credentials on the listing
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'
Run catalog sync
wp hilucy acuity-sync --listing=14216
Preview WC product changes (dry run)
wp hilucy acuity-sync --listing=14216 --with-products --dry-run
Create WC products
wp hilucy acuity-sync --listing=14216 --with-products
Verify the sync
wp hilucy acuity-match --listing=14216
wp hilucy acuity-products --listing=14216
Configure webhooks in Acuity
https://your-site.com/wp-json/hilucy/v1/acuity-webhook
(Optional) Set up per-type add-on filtering
wp hilucy acuity-addon-map --listing=14216 --seed
SOP 2: Update a Service Price
Change the price in Acuity
Wait for automatic sync (or trigger manually)
wp hilucy acuity-sync --listing=14216 --with-products
Verify
SOP 3: Add a New Service in Acuity
Create the appointment type in Acuity
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.
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
Delete or deactivate the appointment type in Acuity
Run a sync
is_active=0) in the wp_acuity_* tables. The WC product will be set to draft if the calendar was removed.(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
Find the WC order in wp-admin → Orders
Check order item meta for
_acuity_booking_error
Check
debug.log for detailed logging
Common causes
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
Create appointment manually in Acuity if needed
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
wp hilucy acuity-sync --listing=14216 --with-products.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._acuity_booking_error on the order item. An admin must then create the appointment manually in Acuity.--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.hilucy_mxn_usd_rate filter. It is not automatically updated from external exchange rate APIs.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.