Cal.com Integration
Knowledge > Integrations > Cal.com
What it is / why we use it
Cal.com is the scheduling platform used in two distinct ways: (1) as an embedded booking widget on churchwiseai.com so prospects can book a free demo directly, and (2) as an optional integration that Pro-tier churches can connect so their voice agent or chatbot can book pastoral appointments on behalf of visitors — with full availability checking and real-time booking, no human required. The embed requires no API key; the per-church voice/chatbot integration requires a Cal.com API key per church stored in church_voice_agents.
Account Info
- Platform: Cal.com (app.cal.com)
- Founder account: john-moelker-jwxe4k (from the embed
calLinkin/book) - Agent access: Demo bookings visible at app.cal.com. No agent CLI configured for Cal.com.
- Customer accounts: Each church on Voice Pro or Bundle Pro sets up their own Cal.com account and provides their API key via the admin dashboard settings.
How Used Per Product
| Context | Method | Details |
|---|---|---|
| churchwiseai.com/book | Embed (no API key) | @calcom/embed-react widget, links to john-moelker-jwxe4k/churchwiseai-chat-voice-demo event |
| Voice Agent (Pro tier) | Cal.com REST API v2 | Checks availability, books appointments live during a phone call |
| Chatbot (Pro tier) | Cal.com REST API v2 | Offers booking links and books via book_appointment tool |
| Founder dashboard | Link only | Demo bookings listed as a funnel source in MarketingFunnels component |
Tier Availability
| Tier | Cal.com Integration |
|---|---|
| Starter Chat | Not available |
| Starter Voice | Not available |
| Pro Chat | Available (book_appointment tool unlocked) |
| Pro Voice | Available (check_availability + book_appointment tools unlocked) |
| Pro Bundle | Available (both agents) |
| Suite | Available |
The admin dashboard shows a LockedFeature component for Starter-tier churches with upgrade prompt to "Voice Pro."
The /book Embed (Demo Booking)
Location: churchwiseai-web/src/app/book/page.tsx
Package: @calcom/embed-react v1.5.3
Event link: john-moelker-jwxe4k/churchwiseai-chat-voice-demo
Branding: Sacred Gold (#D4AF37) applied via cssVarsPerTheme
Layout: Month view, light theme, event type details visible
No API key required — the embed is purely client-side using Cal.com's public embed script
The /book page is the primary booking path for prospects. It is linked from the demo page, the navigation, and CTAs across the site.
Per-Church Voice/Chatbot Integration
Church Configuration
Churches store two fields in church_voice_agents:
| Field | Type | Purpose |
|---|---|---|
cal_event_type_id | text | Cal.com event type ID (integer stored as string) |
cal_api_key | text | Cal.com API key (e.g., cal_live_...) — stored encrypted/secured |
The admin dashboard exposes these as settings fields (obscured with •••••••• once set). Updated via POST /api/premium/update.
has_cal_api_key (boolean) is computed server-side and passed to the dashboard so the key presence is known without exposing the key value to the client.
Voice Agent Integration
File: churchwiseai-web/voice-agent-livekit/verticals/church/integrations/cal.py
API version: Cal.com v2 (cal-api-version: 2024-08-13)
API base: https://api.cal.com/v2
Two @loopback_tool decorated functions:
check_availability(preferred_date: YYYY-MM-DD)
- Calls
GET /v2/slots/availablewitheventTypeId,startTime,endTime - Returns: "Available slots on {date}: 9:00 AM, 10:30 AM, ..."
- If no key/event type configured: returns "Appointment scheduling is not configured for this church."
book_appointment(slot_time, caller_name, caller_email, caller_phone, notes)
- Calls
POST /v2/bookingswith attendee info, eventTypeId, and slot ISO string - Defaults timezone to
America/New_Yorkunlesschurch_timezoneis set in turn env - On success: sends appointment confirmation email via
core.notifications.send_appointment_confirmation_email - On failure: raises
RuntimeError(caught by the voice agent framework)
Keys are loaded from church_voice_agents at session init and injected into turn_env via turn_processor.py.
Chatbot Integration
File: churchwiseai-web/src/lib/chatbot-tools.ts
The chatbot's book_appointment tool (case 'book_appointment' in the tool dispatch) handles the same flow via the HTTP API. The chatbot system prompt includes:
"CRITICAL: When someone wants to meet with, talk to, schedule time with, or book a meeting with {pastorName}, you MUST use the book_appointment tool — do NOT use capture_visitor_contact for scheduling requests."
This conditional is active only when cal_event_type_id AND cal_api_key are both set for the church's voice agent config. If not configured, the chatbot falls back to offering a callback request or directing to church contact info.
Key Environment Variables
Cal.com requires no global environment variables. All credentials are per-church, stored in the church_voice_agents database table:
| Field | Where Stored | Scope |
|---|---|---|
cal_api_key | church_voice_agents DB row | Per-church; set by admin via settings UI |
cal_event_type_id | church_voice_agents DB row | Per-church; event type integer ID |
CLI / API Patterns & Gotchas
API version header is required:
The Cal.com v2 API requires cal-api-version: 2024-08-13 on every request. Without it, requests fail or return unexpected responses. This is hardcoded in cal.py.
Event type ID must be an integer in the request body:
The event type ID is stored as a string in the DB but must be cast to int in book_appointment_api() before sending to Cal.com. The check_availability_api function passes it as a query param (string is fine there).
Default timezone fallback:
If church_timezone is not set in the voice agent config, bookings default to America/New_York. This could create confusion for West Coast churches. Set church_timezone in church_voice_agents for each church.
Embed namespace:
The book page uses Cal namespace "book" for the embed. This namespace is referenced in both getCalApi and the Cal component. Changing it would break the embed UI configuration.
Confirmation email on booking:
After a successful voice agent booking, core.notifications.send_appointment_confirmation_email is called fire-and-forget. Errors are logged but do not fail the booking.
Failure Modes & Recovery
| Failure | Behavior | Recovery |
|---|---|---|
cal_api_key or cal_event_type_id not set | Tool returns "not configured" message; no crash | Church admin must enter credentials in Settings → Integrations tab |
| Cal.com API returns non-2xx | RuntimeError raised; voice agent catches and reports | Check church's Cal.com account status, event type ID, and API key validity |
| Wrong event type ID | Availability check fails with 404 or empty slots | Verify event type ID in church's Cal.com account (Settings → Event Types) |
| Expired or revoked API key | API calls fail | Church admin regenerates API key in Cal.com and updates in dashboard |
| Embed fails to load on /book | White box or loading spinner stuck | Check @calcom/embed-react package version; Cal.com status page for outages |
| Timezone mismatch in booking | Attendee receives wrong time in confirmation | Set church_timezone correctly in voice agent settings |
Cost Model / Usage Limits
- ChurchWiseAI's own Cal.com (for demo bookings): Cal.com Free tier covers the demo use case (1 event type, unlimited bookings)
- Per-church integration: Each church needs its own Cal.com account. Cal.com Free allows 1 active event type. Cal.com Teams ($12/user/month) allows multiple event types and team scheduling.
- API rate limits: Cal.com v2 API — undocumented but generous for per-church usage (not a concern at current scale)
@calcom/embed-react: Free npm package, no license cost
See Also
- Google Workspace Integration — Cal.com bookings appear in Google Calendar; founder calendar tab shows demo bookings
churchwiseai-web/voice-agent-livekit/verticals/church/integrations/cal.py— Voice agent Cal.com toolschurchwiseai-web/src/lib/chatbot-tools.ts— Chatbotbook_appointmentimplementationchurchwiseai-web/src/app/book/page.tsx— Demo booking embed page