- Automation Plugins -
-- Automate your business with powerful plugins that run on schedules. Send emails, - generate reports, and create custom workflows - all without writing complex code. -
-- Key Features -
--
-
- Safe Scripting - Write Python-like code with if/else, loops, variables -
- Flexible Scheduling - Run daily, weekly, hourly, or on cron schedules -
- Resource Protected - Automatic limits prevent abuse -
- Pre-built Templates - Start with ready-made plugins -
- What You Can Automate -
--
-
-
-
- Send weekly summary reports to managers -
- -
-
- Re-engage customers who haven't booked in 60 days -
- -
-
- Alert when bookings are unusually low -
- -
-
- Send birthday wishes with discount codes -
- -
-
- Generate custom analytics and export data -
- -
-
- Integrate with external services via webhooks -
-
- Quick Start -
-- Create your first automation in 3 simple steps: -
--
-
- Write your script - Use simple Python code to access your data -
- Set a schedule - Choose when and how often to run -
- Activate & monitor - Your automation runs automatically -
- That's it! This script counts scheduled appointments and logs the result. - It runs automatically on your schedule. -
-- How It Works -
-- Your scripts run in a secure sandbox with access to your business data through - a simple API object. -
-- Available API Methods -
--
-
api.get_appointments()- Get your appointments
- api.get_customers()- Get your customers
- api.send_email()- Send emails
- api.create_appointment()- Create appointments
- api.log()- Debug logging
-
- Execution Flow -
--
-
- Script is validated for safety -
- Loop guards injected to prevent infinite loops -
- Executed with resource limits (30s timeout, 50 API calls) -
- Results logged for audit trail -
- Next run automatically scheduled -
- Built-in Plugins -
-- Ready-to-use plugins for common business tasks. Just configure and activate. -
-- How to Use Built-in Plugins -
--
-
- - 1. - Navigate to Automation in your dashboard - -
- - 2. - Click "Create New Task" - -
- - 3. - Select a built-in plugin from the dropdown - -
- - 4. - Configure the plugin settings - -
- - 5. - Set your schedule and activate - -
- Custom Scripts -
-- Write your own automation logic with Python. Access your data, write if/else logic, - use loops, and create powerful custom workflows. -
-- What You Can Use -
--
-
- ✓ if/else statements -
- ✓ for/while loops -
- ✓ Variables & lists -
- ✓ Dictionaries -
- ✓ String formatting -
- ✓ Math operations -
- What's Blocked -
--
-
- ✗ import statements -
- ✗ File system access -
- ✗ eval/exec -
- ✗ Network access* -
- *Except approved API calls via api.http_get() -
-- Template Variables -
-- Make your plugins reusable and shareable with powerful template variables. The system supports - four types of templates for maximum flexibility. -
- - {/* 1. PROMPT Variables */} -- 1. User Input (PROMPT) -
-- Prompt users for custom values during plugin installation. The system automatically - generates a configuration form based on your template variables. -
-{'{{PROMPT:variable|description}}'}
- - Required field
- {'{{PROMPT:variable|description|default}}'}
- - Optional field with default value
- {'{{PROMPT:variable|description|default|textarea}}'}
- - Multi-line text input (for email bodies, long messages)
- - Field Type Detection -
-
- The system automatically detects field types from variable names and descriptions: email for email validation,
- number for numeric inputs, message/body/content for textareas, url/webhook for URLs.
- You can override this by explicitly specifying the type as the 4th parameter.
-
- Example: {'{{PROMPT:manager_email|Manager email address}}'}
-
- With default: {'{{PROMPT:discount|Discount code|SAVE20}}'}
-
- 2. Business Context (CONTEXT) -
-- Automatically filled with business information from the system. No user input required! -
-- Benefit: Users don't need to manually enter data that's already in the system! -
-- 3. Date Helpers (DATE) -
-- Pre-calculated dates without writing datetime code. All dates return YYYY-MM-DD format. -
-- 4. Insertion Codes (Dynamic Content) -
-- Use insertion codes within your PROMPT template text (like email bodies) to inject dynamic content - at runtime. These are automatically replaced with actual values when the plugin executes. -
-- Business Information: -
-{'{{BUSINESS_NAME}}'} - Your business name{'{{BUSINESS_EMAIL}}'} - Business contact email{'{{BUSINESS_PHONE}}'} - Business phone number- Customer & Appointment Data: -
-{'{{CUSTOMER_NAME}}'} - Customer's name (in appointment contexts){'{{CUSTOMER_EMAIL}}'} - Customer's email address{'{{APPOINTMENT_TIME}}'} - Full appointment date and time{'{{APPOINTMENT_DATE}}'} - Appointment date only{'{{APPOINTMENT_SERVICE}}'} - Service name- Date & Time: -
-{'{{TODAY}}'} - Today's date (YYYY-MM-DD){'{{NOW}}'} - Current date and timeExample: Email Template with Insertion Codes
-
-{`email_body = '{{PROMPT:email_body|Email Message|Hi {{CUSTOMER_NAME}},
-
-This is a reminder about your appointment:
-
-Date/Time: {{APPOINTMENT_TIME}}
-Service: {{APPOINTMENT_SERVICE}}
-
-If you have questions, contact us at {{BUSINESS_EMAIL}}
-
-Best regards,
-{{BUSINESS_NAME}}||textarea}}'`}
-
- - 5. Automatic Validation -
-- The system automatically detects field types and validates input: -
-- Pro Tip: Combine all template types for maximum power! Use CONTEXT - for business info, DATE for time logic, PROMPT for user configuration, and Insertion Codes - within your email templates for personalized dynamic content. -
-- Configure Plugin -
- Step 2 of 3 -- Number of days before a customer is considered inactive -
- -- Promotional discount code to offer -
- -- Default: SAVE20 -
-- Email address for reports and notifications -
- -- - Email validation enabled -
-- Custom message to include in re-engagement emails -
- -- Auto-filled values: business_name, owner_email, phone - (no input needed) -
-- What Gets Replaced -
-- Benefits of CONTEXT Variables -
--
-
- ✓ No user input required - fully automatic -
- ✓ Always up-to-date with current business info -
- ✓ Prevents typos in business name/email -
- ✓ Faster plugin installation -
- Benefits of DATE Helpers -
--
-
- ✓ No datetime imports or code needed -
- ✓ Simpler, more readable scripts -
- ✓ Consistent date formatting (YYYY-MM-DD) -
- ✓ Human-friendly expressions (+7d, monday) -
- Benefits of Default Values -
--
-
- ✓ Faster setup with pre-filled sensible defaults -
- ✓ Users can accept defaults or customize -
- ✓ Makes fields optional instead of required -
- ✓ Great for expert/beginner modes -
- API Methods Reference -
-
- All scripts have access to the api object with these methods. Each method shows its signature, available filters/parameters, and return data structure.
-
Appointments
-
- api.get_appointments(**filters) → List[dict]
-
- status — Exact match: SCHEDULED, COMPLETED, CANCELED, NO_SHOW, EN_ROUTE, IN_PROGRESS, AWAITING_PAYMENT, PAIDstatus__in — Multiple statuses: ['SCHEDULED', 'COMPLETED']start_time__gt — After this timestart_time__gte — On or after this timestart_time__lt — Before this timestart_time__lte — On or before this timeend_time__gt — Ends after this timeend_time__gte — Ends on or afterend_time__lt — Ends before this timeend_time__lte — Ends on or beforecreated_at__gte — Created on or aftercreated_at__lte — Created on or beforeupdated_at__gte — Updated on or afterupdated_at__lte — Updated on or beforestart_date — Appointments starting on or after this dateend_date — Appointments starting on or before this dateservice_id — Filter by service IDlocation_id — Filter by location IDcustomer_id — Filter by customer IDresource_id — Filter by resource/staff IDtitle__icontains — Title contains textnotes__icontains — Notes contain textdeposit_amount__gte — Deposit ≥ amountdeposit_amount__lte — Deposit ≤ amountfinal_price__gte — Final price ≥ amountfinal_price__lte — Final price ≤ amounthas_deposit — True/False: has a deposithas_final_price — True/False: has final pricelimit — Max results (default 100, max 1000)
- api.create_appointment(title, start_time, end_time, notes) → dict
-
- title — Appointment title (required)start_time — ISO datetime (required)end_time — ISO datetime (required)notes — Optional notes
- api.update_appointment(id, **updates) → dict
-
- title — New titlestatus — SCHEDULED, COMPLETED, CANCELED, NO_SHOWnotes — Updated notesstart_time / end_time — Reschedule
- api.get_recurring_appointments(**filters) → List[dict]
-
- id — Exact recurring appointment IDstatus — active, paused, canceledstatus__in — Multiple statuses ['active', 'paused']title__icontains — Title contains textrecurring_pattern__icontains — Recurrence rule containsstart_time__gte/lte/gt/lt — Time comparisonscustomer_id — Filter by customer IDresource_id — Filter by resource IDlimit — Max results (default 100, max 500)Customers
-
- api.get_customers(**filters) → List[dict]
-
- id — Exact customer IDemail — Exact email matchemail__icontains — Email contains textname__icontains — Name contains texthas_email — true/false, filter by email presencehas_phone — true/false, filter by phone presenceis_active — Filter by active statuscreated_at__gte/lte/gt/lt — Date comparisons (ISO format)limit — Max results (default 100, max 1000)Resources
-
- api.get_resources(**filters) → List[dict]
-
- id — Exact resource IDtype — STAFF, ROOM, or EQUIPMENTtype__in — Multiple types ['STAFF', 'ROOM']name__icontains — Name contains textdescription__icontains — Description contains textis_active — true/false (default: true)is_mobile — Filter by mobile capabilitylocation_id — Filter by locationuser_id — Filter by linked user IDmax_concurrent_events__gte/lte — Concurrency comparisonslimit — Max results (default 100, max 500)
- api.get_resource_availability(resource_id, ...) → dict
-
- resource_id — Resource ID (required)days — Number of days to checkstart_date — Start of period (YYYY-MM-DD)end_date — End of period (YYYY-MM-DD)Services
-
- api.get_services(**filters) → List[dict]
-
- id — Exact service IDname__icontains — Name contains textdescription__icontains — Description contains textis_active — true/false (default: true)is_global — Filter global servicesvariable_pricing — Filter by variable pricingrequires_deposit — Filter by deposit requiredlocation_id — Filter by locationduration__gte/lte — Duration comparisons (minutes)price__gte/lte — Price comparisons (decimal)price_cents__gte/lte — Price comparisons (cents)limit — Max results (default 100, max 500)
- api.get_service_stats(service_id, days) → dict
-
- service_id — Service ID (required)days — Period in days (default 30)Locations
-
- api.get_locations(**filters) → List[dict]
-
- id — Exact location IDname__icontains — Name contains textcity__icontains — City contains textstate — Exact state matchcountry — Exact country matchpostal_code — Exact postal codetimezone — Exact timezoneis_active — true/false (default: true)is_primary — Filter primary locationhas_phone — Has phone numberhas_email — Has email addresslimit — Max results (default 100, max 500)
- api.get_location_stats(location_id, days) → dict
-
- location_id — Location ID (required)days — Period in days (default 30)Staff
-
- api.get_staff(**filters) → List[dict]
-
- id — Exact staff IDrole — staff, manager, or ownerrole__in — Multiple roles ['staff', 'manager']email — Exact email matchemail__icontains — Email contains textname__icontains — Full name contains textfirst_name__icontains — First name contains textlast_name__icontains — Last name contains textis_active — true/false (default: true)has_phone — Has phone numberlimit — Max results (default 100, max 500)
- api.get_staff_performance(staff_id=None, days=30) → dict
-
- staff_id — Specific staff (optional, omit for all)days — Period in days (default 30)Communication
-
- api.send_email(to, subject, body) → bool
-
- to — Email address OR customer ID (int)subject — Email subject (max 200 chars)body — Email body (max 10,000 chars)
- api.send_sms(to, message) → bool
-
- to — Phone number in E.164 format (+15551234567)message — SMS text (max 1600 chars)
- api.get_sms_balance() → dict
-
-
- api.get_email_templates(**filters) → List[dict]
-
- id — Exact template IDtemplate_type — Exact template typetemplate_type__in — Multiple template typesname__icontains — Name contains textsubject__icontains — Subject contains textis_active — true/false (default: true)created_at__gte/lte/gt/lt — Date comparisons (ISO format)limit — Max results (default 100, max 500)
- api.send_template_email(template_id, to, variables) → bool
-
- template_id — Email template IDto — Recipient email addressvariables — Dict of template variablesPayments
- Requires: payment_processing -
- api.get_payments(**filters) → List[dict]
-
- id — Exact payment IDstatus — pending, completed, failed, refundedstatus__in — Multiple statuses ['completed', 'pending']currency — Currency code (USD, EUR, etc.)customer_id — Filter by customer IDcustomer_email__icontains — Customer email contains textamount__gte/lte — Amount comparisons (decimal)amount_cents__gte/lte — Amount comparisons (cents)created_at__gte/lte/gt/lt — Date comparisons (ISO format)completed_at__gte/lte/gt/lt — Completion date comparisonsdays_back — Limit to last N dayslimit — Max results (default 100, max 500)
- api.get_invoices(**filters) → List[dict]
-
- id — Exact invoice IDstatus — draft, sent, paid, overdue, canceledstatus__in — Multiple statuses ['paid', 'sent']currency — Currency code (USD, EUR, etc.)plan_name__icontains — Plan name contains texttotal__gte/lte — Total amount comparisonstotal_cents__gte/lte — Total comparisons (cents)created_at__gte/lte/gt/lt — Date comparisons (ISO format)paid_at__gte/lte/gt/lt — Payment date comparisonsperiod_start__gte/lte/gt/lt — Period start comparisonsperiod_end__gte/lte/gt/lt — Period end comparisonsdays_back — Limit to last N dayslimit — Max results (default 100, max 500)
- api.get_revenue_stats(days) → dict
-
- days — Period in days (default 30)Contracts
- Requires: can_use_contracts -
- api.get_contracts(**filters) → List[dict]
-
- id — Exact contract IDstatus — draft, sent, signed, expired, canceledstatus__in — Multiple statuses ['sent', 'signed']customer_id — Filter by customer IDcustomer_email__icontains — Customer email contains texttitle__icontains — Title contains texttemplate_name__icontains — Template name contains textexpires_at__gte/lte/gt/lt — Expiration date comparisonssent_at__gte/lte/gt/lt — Sent date comparisonscreated_at__gte/lte/gt/lt — Date comparisons (ISO format)limit — Max results (default 100, max 500)
- api.get_expiring_contracts(days) → List[dict]
-
- days — Contracts expiring within N days (default 30)Video
- Requires: can_add_video_conferencing -
- api.create_video_meeting(...) → dict
-
- provider — zoom, google_meet, or teamstitle — Meeting titleduration — Duration in minutesstart_time — ISO datetime (optional)Analytics
- Requires: advanced_reporting -
- api.get_analytics(**filters) → dict
-
- days — Period in days (default 30)metrics — List: bookings, customers, services, staff, revenue
- api.get_booking_trends(days, group_by) → dict
-
- days — Period in days (default 30)group_by — day, week, hour, or weekdayUtilities
-api.log(message) → None
- api.count(items) → int
- api.sum(items) → float
- api.filter(items, lambda) → list
-
-
- External HTTP Methods
-
- All URLs must be whitelisted before use
-api.http_get(url, headers) → str
- api.http_post(url, data, headers) → str
- api.http_put(url, data, headers) → str
- api.http_patch(url, data, headers) → str
- api.http_delete(url, headers) → str
- To request URL whitelisting:
-- Email pluginaccess@smoothschedule.com with - the URLs, HTTP methods needed, and an exact copy of your code. -
-- Command Reference -
-- Scripts run in a secure sandbox with a restricted set of Python commands. - This prevents malicious code while giving you the power to write useful automations. -
-- Allowed Control Flow & Operators -
-- All standard Python control flow statements and operators are supported: -
-- Allowed Built-in Functions -
-- These Python built-in functions are available in your scripts: -
-- Blocked Operations -
-- These operations are disabled for security: -
-
- Note: While you cannot use import,
- the datetime module is available for use in your scripts
- via from datetime import datetime, timedelta. This is
- pre-imported in the execution context.
-
- Allowed: Basic Python Operations -
-- Blocked: Dangerous Operations -
-- Schedule Types -
-- Choose when and how often your automation runs. -
-- Cron Expression -
-- Flexible scheduling using cron syntax: -
--
-
0 9 * * 1- Every Monday at 9 AM
- 0 0 * * *- Daily at midnight
- 0 */2 * * *- Every 2 hours
-
- Fixed Interval -
-
- Run every N minutes: interval_minutes: 60
-
- One-Time -
-
- Run once at a specific datetime: run_at: "2025-02-01T10:00:00Z"
-
- Common Schedule Examples -
-- Manage Tasks -
-- Create, update, and monitor your scheduled automation tasks through the dashboard. -
-- Dashboard Actions -
--
-
- Create: Click "New Automation" to create a task -
- Edit: Click on any task to modify its settings -
- Pause/Resume: Toggle tasks on/off without deleting -
- Delete: Remove tasks you no longer need -
- View Logs: See execution history and results -
- Test Run: Execute manually to test your script -
- Task Management Tips -
--
-
- - • - Always test your script with "Run Now" before scheduling - -
- - • - Check execution logs regularly to catch errors early - -
- - • - Pause tasks during maintenance or high-traffic periods - -
- - • - Use descriptive names to identify tasks at a glance - -
- Example: Win Back Lost Customers -
-- Automatically identify customers who haven't booked in 60 days and send them - a personalized discount code to win them back. -
-- Expected Results -
--
-
- • 15-20% of contacted customers return -
- • $3,000-5,000/month in recovered revenue -
- • Runs automatically every Monday -
- Example: Low Booking Alerts -
-- Get notified when upcoming bookings are unusually low so you can take action - before it impacts revenue. -
-- Use Case -
-- Spa manager gets daily email if next week has less than 10 bookings, - prompting them to run a promotion or send reminders to past customers. -
-- Example: Weekly Reports -
-- Automatically generate and email weekly summary reports with appointment statistics. -
-- What It Does -
--
-
- Counts appointments by status (scheduled, completed, canceled) -
- Calculates revenue from completed appointments -
- Emails formatted report to manager -
- Runs every Monday at 9 AM -
- Safety Features -
-- Multiple layers of protection ensure your data and our servers stay safe. -
-- Blocked: File System Access -
-- Blocked: Code Injection -
-- Plugin Licensing -
-- Understand the licensing terms for plugins you create and share on SmoothSchedule. -
- -- Private Plugins -
-- Plugins you create for personal use remain private. You retain full ownership and control: -
--
-
- Only accessible within your business account -
- Not visible in the public marketplace -
- You choose any license you want (or none) -
- SmoothSchedule can execute your code to provide the service -
- Marketplace Plugins (Public Sharing) -
-- When you publish a plugin to the marketplace, you agree to the{' '} - SmoothSchedule Community Plugin License: -
- -- SmoothSchedule Community Plugin License (SCPL) -
-- You grant the following rights: -
--
-
- - SmoothSchedule Rights: SmoothSchedule may use, execute, host, and distribute your plugin code - to provide the marketplace service - -
- - User Rights: Other SmoothSchedule users may install, use, and modify your plugin - for their own business purposes - -
- - Attribution: Your authorship will be credited in the marketplace listing - -
- - Modifications: Users may adapt your code to their needs, but cannot republish - modified versions to the marketplace without your permission - -
- - Revocation: You may unpublish your plugin at any time. Existing installations - will continue to function, but new installs will be disabled - -
- You retain: Copyright ownership, ability to license elsewhere, right to unpublish -
-- Similar to: MIT License + SmoothSchedule Service Rights -
-- Code Verification & Security -
-- When you upload a plugin (private or marketplace): -
--
-
- Original code is stored for security verification -
- Changing code after URL whitelisting will fail upload -
- SmoothSchedule may review code for security compliance -
- Malicious code will result in account suspension -
- Private vs. Marketplace Plugins -
-
-
- Important to Know
-
- -
-
- - SmoothSchedule Service Rights: By uploading any plugin, you grant SmoothSchedule - the right to execute your code to provide the automation service - -
- - No Warranty: Plugins are provided "as-is" without warranty. Test thoroughly - before deploying to production - -
- - Compliance: You are responsible for ensuring your plugin complies with all - applicable laws and regulations - -
- - Data Privacy: Handle customer data responsibly and in compliance with GDPR, - CCPA, and other privacy laws - -
- Should I Publish to Marketplace? -
--
-
- You want to help the community -
- Your plugin solves a common problem -
- You're comfortable with the SCPL terms -
- You want recognition as the author -
-
-
- Contains business-specific logic -
- Uses proprietary algorithms -
- Integrates with private internal systems -
- You want to restrict access -
- Resource Limits -
-- Automatic limits prevent resource abuse and keep the platform fast for everyone. -
-- What Happens When Limits Are Hit? -
--
-
- Script stops gracefully with clear error message -
- Execution logged with failure status -
- You receive notification in your dashboard -
- Task will retry on next scheduled run -
- Optimization Tips -
--
-
- - • - Use filters to reduce data fetched (limit, status, dates) - -
- - • - Avoid nested loops where possible - -
- - • - Cache API results in variables instead of repeated calls - -
- - • - Break large tasks into smaller scheduled tasks - -