Category: Software Development

  • How to Built a Production Level Booking System (Voice AI – Vapi & n8n) – Part 3

    How to Built a Production Level Booking System (Voice AI – Vapi & n8n) – Part 3

    In “How to Built a Production Level Booking System (Voice AI – Vapi & n8n) – Part 3”, you’ll finish connecting Vapi to n8n through webhooks to complete a reliable appointment booking flow. You’ll set up check-availability and booking routes, create custom Vapi tools, and run live call tests so your AI agent can read Google Calendar and schedule appointments automatically.

    The video walks through setup review, Vapi tools and assistant creation, handling the current time and Vapi variables, building the booking route, and a final end-to-end test, with timestamps marking each segment. You’ll also pick up practical tips to harden the system for production use with real clients.

    Review of System Architecture and Goals

    You’re building a production-ready voice-driven booking system that connects a voice AI platform (Vapi) to automation workflows (n8n) and Google Calendar via webhooks. The core components are Vapi for voice interaction and assistant orchestration, n8n for server-side workflow logic and integrations, Google Calendar as your authoritative schedule store, and webhook endpoints that carry structured requests and responses between Vapi and n8n. Each component plays a clear role: Vapi collects intent and slots, n8n enforces business rules and talks to Google, and webhooks provide the synchronous bridge for availability checks and bookings.

    At production level you should prioritize reliability, low latency, idempotency, and security. Reliability means retries, error handling, and graceful degradation; low latency means designing quick synchronous paths for user-facing checks while offloading heavy work to async flows when possible; idempotency prevents double-bookings on retries; security encompasses OAuth 2.0 for Google, secrets encryption, signed webhooks, and least-privilege scopes. You’ll also want observability and alerts so you can detect and fix problems quickly.

    Below is a compact diagram of the data flow from voice input to calendar booking and back. This ASCII diagram maps the steps so you can visualize end-to-end behavior.

    Vapi (Voice) –> Webhook POST /check-availability –> n8n workflow –> Google Calendar (freeBusy/events) –> n8n processing –> Webhook response –> Vapi (synthesizes reply to user) Vapi (Voice) –> Webhook POST /book –> n8n workflow (validate/idempotency) –> Google Calendar (create event) –> n8n confirms & returns event data –> Vapi (notifies user)

    You should expect robust behaviors for edge cases. If appointments overlap, your system should detect conflicts via free/busy checks and present alternative slots or ask the user to pick another time. If requested times are unavailable, the system should offer nearby slots considering working hours, buffers, and participant availability. For partial failures (e.g., calendar created but notification failed), you must implement compensating actions and clear user messaging.

    Nonfunctional requirements include scalability (handle spikes in voice requests), monitoring (metrics, logs, and tracing for both Vapi and n8n), cost control (optimize Google API calls and avoid polling), and compliance (store minimal PII, encrypt tokens, and follow regional data rules).

    Environment and Prerequisite Checks

    Before you wire everything up, verify your accounts and environments. Confirm that your Vapi account is active, you have API keys or the required agent credentials, and workspace settings (such as callback URLs and allowed domains) are configured for production. Check that Vapi supports secure storage for tools and variables you’ll need.

    Validate that your n8n instance is online and reachable, that you can create workflows, and that webhook credentials are set (e.g., basic auth or signature secret). Ensure endpoints are addressable by Vapi (public URL or tunnel), and that you can restart workflows and review logs.

    Confirm Google API credentials exist in the correct project, with OAuth 2.0 client ID/secret and refresh-token flow working. Make sure Calendar API is enabled and the service account or OAuth user has access to the calendars you will manage. Create a test calendar to run bookings without affecting production slots.

    Plan environment separation: local development, staging, and production. Keep different credentials for each and make configuration environment-driven (env vars or secret store). Use a config file or deployment tooling to avoid hardcoding endpoints.

    Do network checks: ensure your webhook endpoints are reachable from Vapi (public IP/DNS), have valid TLS certificates, and are not blocked by firewalls. Confirm port routing, DNS, and TLS chain validity. If you use a reverse proxy or load balancer, verify header forwarding so you can validate signatures.

    Setting Up Custom Tools in Vapi

    Design each custom tool in Vapi with a single responsibility: check availability, create booking, and cancel booking. For each tool, define clear inputs (start_time, end_time, duration, timezone, user_id, idempotency_key) and outputs (available_slots, booking_confirmation, event_id, error_code). Keep tools small so you can test and reuse them easily.

    Define request and response schemas in JSON Schema or a similar format so tools are predictable and easy to wire into your assistant logic. This will make validation and debugging much simpler when Vapi sends requests to your webhooks.

    Implement authentication in your tools: store API keys and OAuth credentials securely inside Vapi’s secrets manager or a vault. Ensure tools use those secrets and never log raw credentials. If Vapi supports scoped secrets per workspace, use that to limit blast radius.

    Test tools in isolation first using mocked webhook endpoints or stubbed responses. Verify that given well-formed and malformed inputs, outputs remain stable and error cases return consistent, actionable error objects. Use these tests during CI to prevent regressions.

    Adopt a versioning strategy for tools: use semantic versioning for tool schemas and implementation. Keep migration plans so old assistants can continue functioning while new behavior is deployed. Provide backward-compatible changes or a migration guide for breaking changes.

    Creating the Assistant and Conversation Flow

    Map user intents and required slot values up front: intent for booking, intent for checking availability, cancelling, rescheduling, and asking about existing bookings. For bookings, common slots are date, start_time, duration, timezone, service_type, and attendee_email. Capture optional information like notes and preferred contact method.

    Implement prompts and fallback strategies: if a user omits the duration, ask a clarifying question; if the time is ambiguous, ask to confirm timezone or AM/PM. Use explicit confirmations before finalizing a booking. For ambiguous or noisy voice input, use repeat-and-confirm patterns to avoid mistakes.

    Integrate your custom tools into assistant flows so that availability checks happen as soon as you have a candidate time. Orchestrate tool calls so that check-availability runs first, and booking is only invoked after confirmation. Use retries and small backoffs for transient webhook failures and provide clear user messaging about delays.

    Leverage session variables to maintain context across multi-turn dialogs—store tentative booking drafts like proposed_time, duration, and chosen_calendar. Use these variables to present summary confirmations and to resume after interruptions.

    Set conversation turn limits and confirmation steps: after N turns of ambiguity, offer to switch to a human or send a follow-up message. Implement explicit cancellation flows that clear session state and, if necessary, call the cancel booking tool if a provisional booking exists.

    Implementing Time Handling and Current Time Variable

    Standardize time representation using ISO 8601 strings and always include timezone offsets or IANA timezone identifiers. This removes ambiguity when passing times between Vapi, n8n, and Google Calendar. Store timezone info as a separate field if helpful for display.

    Create a Vapi variable for current time that updates at session start and periodically as needed. Having session-level current_time lets your assistant make consistent decisions during a conversation and prevents subtle race conditions when the user and server cross midnight boundaries.

    Plan strategies for timezone conversions: convert user-provided local times to UTC for storage and Google Calendar calls, then convert back to the user’s timezone for presentation. Keep a canonical timezone for each user profile so future conversations default to that zone.

    Handle DST and ambiguous local times by checking timezone rules for the date in question. If a local time is ambiguous (e.g., repeated hour at DST end), ask the user to clarify or present both UTC-offset options. For bookings across regions, let the user pick which timezone they mean and include timezone metadata in the event.

    Test time logic with deterministic time mocks in unit and integration tests. Inject a mocked current_time into your flows so that you can reproduce scenarios like DST transitions or midnight cutovers consistently.

    Vapi Variables and State Management

    Differentiate ephemeral session variables (temporary booking draft, last asked question) from persistent user data (default timezone, email, consent flags). Ephemeral variables should be cleared when the session ends or on explicit cancellation to avoid stale data. Persistent data should be stored only with user consent.

    Follow best practices for storing sensitive data: tokens and PII should be encrypted at rest and access-controlled. Prefer using Vapi’s secure secret storage for credentials rather than session variables. If you must save PII, minimize what you store and document retention policies.

    Define clear lifecycle rules for variables: initialization at session start, mutation during the flow (with controlled update paths), and cleanup after completion or timeout. Implement TTLs for session data so that abandoned flows don’t retain data indefinitely.

    Allow users to persist booking drafts so they can resume interrupted flows. Implement a resume token that references persisted draft metadata stored in a secure database. Ensure drafts are short-lived or explicitly confirmed to become real bookings.

    Be mindful of data retention and GDPR: record consent for storing personal details, provide user-accessible ways to delete data, and avoid storing audio or transcripts longer than necessary. Document your data flows and retention policies so you can respond to compliance requests.

    Designing n8n Workflows and Webhook Endpoints

    Create webhook endpoints in n8n for check-availability and booking routes. Each webhook should validate incoming payloads (type checks, required fields) before proceeding. Use authentication mechanisms (header tokens or HMAC signatures) to ensure only your Vapi workspace can call these endpoints.

    Map incoming Vapi tool payloads to n8n nodes: use Set or Function nodes to normalize the payload, then call the Google Calendar nodes or HTTP nodes as needed. Keep payload transformations explicit and logged so you can trace issues.

    Implement logic nodes for business rules: time-window validation, working hours enforcement, buffer application, and conflict resolution. Use IF nodes and Switch nodes to branch flows based on availability results or validation outcomes.

    Integrate Google Calendar nodes with proper OAuth2 flows and scopes. Use refresh tokens or service accounts per your architecture, and safeguard credentials. For operations that require attendee management, include attendee emails and appropriate visibility settings.

    Return structured success and error responses back to Vapi in webhook replies: include normalized fields like status, available_slots (array of ISO timestamps), event_id, join_links, and human-readable messages. Standardize error codes and retry instructions.

    Check Availability Route Implementation

    When implementing the check availability route, parse requested time windows and duration from the Vapi payload. Normalize these into UTC and a canonical timezone so all downstream logic uses consistent timestamps. Validate that the duration is positive and within allowed limits.

    Query Google Calendar’s freeBusy endpoint or events list for conflicts within the requested window. freeBusy is efficient for fast conflict checks across multiple calendars. For nuanced checks (recurring events, tentative events), you may need to expand recurring events to see actual occupied intervals.

    Apply business constraints such as working hours, required buffers (pre/post meeting), and slot granularity. For example, if meetings must start on 15-minute increments and require a 10-minute buffer after events, enforce that in the selection logic.

    Return normalized available slots as an array of timezone-aware ISO 8601 start and end pairs. Include metadata like chance of conflict, suggested slots count, and the timezone used. Keep the model predictable so Vapi can present human-friendly options.

    Handle edge cases such as overlapping multi-day events, all-day busy markers, and recurring busy windows. For recurring events that block large periods (e.g., weekly off-times), treat them as repeating blocks and exclude affected dates. For busy recurring events with exceptions, make sure your expand/occurrence logic respects the calendar API’s recurrence rules.

    Booking Route Implementation and Idempotency

    For the booking route, validate all incoming fields (start_time, end_time, attendee, idempotency_key) and re-check availability before finalizing the event. Never assume availability from a prior check without revalidating within a short window.

    Implement idempotency keys so retries from Vapi (or network retries) don’t create duplicate events. Store the idempotency key and the resulting event_id in your datastore; if the same key is submitted again, return the same confirmation rather than creating a new event.

    When creating calendar events, attach appropriate metadata: organizer, attendees, visibility, reminders, and a unique client-side token in the description or extended properties that helps you reconcile events later. Include a cancellation token or secret in the event metadata so you can authenticate cancel requests.

    Return a booking confirmation with the event ID, any join links (for video conferences), and the cancellation token. Also return human-friendly text for the assistant to speak, and structured data for downstream systems.

    Introduce compensating actions and rollback steps for partial failures. For example, if you create the Google Calendar event but fail to persist the booking metadata due to a DB outage, attempt to delete the calendar event and report an error if rollback fails. Keep retryable and non-retryable failures clearly separated and surface actionable messages to the user.

    Conclusion

    You now have a clear path to complete a production-level voice booking system that links Vapi to n8n and Google Calendar via webhooks. Key steps are designing robust tools in Vapi, enforcing clear schemas and idempotency, handling timezones and DST carefully, and building resilient n8n workflows with strong validation and rollback logic.

    Before launching, run through a checklist: validate endpoints and TLS, verify OAuth2 flows and scopes, implement idempotency and retry policies, set up logging and monitoring, test edge cases (DST, overlapping events, network failures), document data retention and consent, and stress test for expected traffic patterns. Secure credentials and enforce least privilege across components.

    For iterative improvements, instrument user journeys to identify friction, introduce async notifications (email/SMS) for confirmations, add rescheduling flows, and consider queuing or background tasks for non-critical processing. As you scale, consider multi-region deployments, caching of calendar free/busy windows with TTLs, and rate-limiting to control costs.

    Next steps include comprehensive integration tests, a small closed beta with real users to gather feedback, and a rollout plan that includes monitoring thresholds and rollback procedures. With these foundations, you’ll be well-positioned to deliver a reliable, secure, and user-friendly voice booking system for real clients.

    If you want to implement Chat and Voice Agents into your business to reduce missed calls, book more appointments, save time, and make more revenue, book a discovery call here: https://brand.eliteaienterprises.com/widget/bookings/elite-ai-30-min-demo-call

  • How to Built a Production Level Booking System (Voice AI – Google Calendar & n8n) – Part 2

    How to Built a Production Level Booking System (Voice AI – Google Calendar & n8n) – Part 2

    In “How to Built a Production Level Booking System (Voice AI – Google Calendar & n8n) – Part 2”, you’ll get a hands-on walkthrough for building a production-ready availability checker that syncs your Google Calendar with n8n. The lesson shows how to craft deterministic workflows, handle edge cases like fully booked or completely free days, and add buffer times so bookings stay reliable.

    You’ll follow a short demo, a recap of Part 1, the main Part 2 build, and a Code Node walkthrough, with previews of Parts 3 and 4 at specific timestamps. By the end, you’ll have the logic to cross-reference busy slots, return only available times, and plug that into your booking flow for consistent scheduling.

    Recap of Part 1 and Objectives for Part 2

    Brief summary of what was built in Part 1 (voice AI intake, basic booking flow)

    In Part 1 you created the voice intake and a basic booking flow that takes a caller’s request, parses intent (date, time preferences, duration), and initiates a provisional booking sequence. You connected your Voice AI (Vapi or another provider) to n8n so that spoken inputs are converted into structured data. You also built the initial UI and backend hooks to accept a proposed slot and create a calendar event when the caller confirms — but you relied on a simple availability check that didn’t handle many real-world cases.

    Goals for Part 2: deterministic availability checking and calendar sync

    In Part 2 your goal is to replace the simple availability heuristic with a deterministic availability checker. You want a component that queries Google Calendar reliably, merges busy intervals, applies working hours and buffers, enforces minimum lead time, and returns deterministic free slots suitable for voice-driven confirmations. You’ll also ensure the system can sync back to Google Calendar in a consistent way so bookings created after availability checks don’t collide.

    Success criteria for a production-ready availability system

    You’ll consider the system production-ready when it consistently returns the same available slots for the same input, responds within voice-interaction latency limits, handles API failures gracefully, respects calendar privacy and least privilege, and prevents race conditions (for example via short-lived holds or transactional checks before final booking). Additionally, success includes test coverage for edge cases (recurring events, all-day events, DST changes) and operational observability (logs, retries, metrics).

    Assumptions and prerequisites (Google Calendar account, n8n instance, Vapi/Voice AI setup)

    You should have a Google Calendar account (or a service account with delegated domain-wide access if you manage multiple users), a running n8n instance that can make outbound HTTPS calls, and your Voice AI (Vapi) configured to send intents into n8n. You also need environment variables or credentials stored securely in n8n for Google OAuth or service-account keys, and agreed booking policies (working hours, buffer durations, minimum lead time).

    Design Goals and Non-Functional Requirements

    Deterministic and repeatable availability results

    You need the availability checker to be deterministic: the same inputs (calendar id, date range, booking duration, policy parameters) should always yield the same outputs. To achieve this, you must standardize timezone handling, use a canonical algorithm for merging intervals, and avoid ephemeral randomness. Determinism makes debugging easier, allows caching, and ensures stable voice interactions.

    Low latency responses suitable for real-time voice interactions

    Voice interactions require quick responses; aim for sub-second to a few-second availability checks. That means keeping the number of API calls minimal (batch freebusy queries rather than many per-event calls), optimizing code in n8n Function/Code nodes, and using efficient algorithms for interval merging and slot generation.

    Resilience to transient API failures and rate limits

    Google APIs can be transiently unavailable or rate-limited. Design retry logic with exponential backoff, idempotent requests where possible, and graceful degradation (e.g., fallback to “please wait while I check” with an async callback). Respect Google’s quotas and implement client-side rate limiting if you’ll serve many users.

    Security, least privilege, and privacy considerations for calendar data

    Apply least privilege to calendar scopes: request only what you need. If you only need freebusy information, avoid full event read/write scopes unless necessary. Store credentials securely in n8n credentials, rotate them, and ensure logs don’t leak sensitive event details. Consider using service accounts with domain delegation only if you control all user accounts, and always ask user consent for personal calendars.

    High-Level Architecture Overview

    Logical components: Voice AI, n8n workflows, Google Calendar API, internal scheduling logic

    Your architecture will have the Voice AI component capturing intent and sending structured requests to n8n. n8n orchestrates workflows that call Google Calendar API for calendar data and then run internal scheduling logic (the deterministic availability checker) implemented in n8n Code nodes or subworkflows. Finally, results are returned to Voice AI and presented to the caller; booking nodes create events when a slot is chosen.

    Data flow from voice intent to returned available slots

    When the caller specifies preferences, Vapi sends an intent payload to n8n containing date ranges, duration, timezone, and any constraints. n8n receives that payload, normalizes inputs, queries Google Calendar (freebusy or events), merges busy intervals, computes free slots with buffers and lead times applied, formats results into a voice-friendly structure, and returns them to Vapi for the voice response.

    Where the availability checker lives and how it interacts with other parts

    The availability checker lives as an n8n workflow (or a callable subworkflow) that exposes an HTTP trigger. Voice AI triggers the workflow and waits for the result. Internally, the workflow splits responsibilities: calendar lookup, interval merging, slot generation, and formatting. The checker can be reused by other parts (booking, rescheduling) and called synchronously for real-time replies or asynchronously to follow up.

    Integration points for future features (booking, cancellations, follow-ups)

    Design the checker with hooks: after a slot is returned, a short hold mechanism can reserve that slot for a few minutes (or mark it as pending via a lightweight busy event) to avoid race conditions before booking. The same workflow can feed the booking workflow to create events, the cancellation workflow to free slots, and follow-up automations for reminders or confirmations.

    Google Calendar Integration Details

    Authentication options: OAuth 2.0 service accounts vs user consent flow

    You can authenticate using OAuth 2.0 user consent (best for personal calendars where users sign in) or a service account with domain-wide delegation (suitable for organizational setups where you control users). OAuth user consent gives user-level permissions and auditability; service accounts are easier for multi-user automation but require admin setup and careful delegation.

    Scopes required and least-privilege recommendations

    Request the smallest set of scopes you need. For availability checks you can often use the freebusy scope and readonly event access: typically https://www.googleapis.com/auth/calendar.freebusy and/or https://www.googleapis.com/auth/calendar.events.readonly. If you must create events, request event creation scope separately at booking time and store tokens securely.

    API endpoints to use for freebusy and events queries

    Use the freebusy endpoint to get busy time ranges for one or more calendars in a single call — it’s efficient and designed for availability checks. You’ll call events.list for more detail when you need event metadata (organizer, transparency, recurrence). For creating bookings you’ll use events.insert with appropriate settings (attendees, reminders, transparency).

    Pagination, timezones, and recurring events handling

    Events.list can be paginated; handle nextPageToken. Always request times in RFC3339 with explicit timezone or use the calendar’s timezone. For recurring events, expand recurring rules when querying (use singleEvents=true and specify timeMin/timeMax) so you get each instance as a separate entry during a range. For freebusy, recurring expansions are handled by the API.

    Availability Checking Strategy

    Using Google Calendar freebusy vs querying events directly and tradeoffs

    freebusy is ideal for fast, aggregated busy intervals across calendars; it’s fewer calls and simpler to merge. events.list gives details and lets you respect transparency or tentative statuses but requires more calls and processing. Use freebusy for initial availability and fallback to events when you need semantics (like ignoring transparent or tentative events).

    Defining availability windows using working hours, exceptions, and overrides

    Define availability windows per-calendar or globally: working hours by weekday (e.g., Mon-Fri 09:00–17:00), exceptions like holidays, and manual overrides (block or open specific slots). Represent these as canonical time ranges and apply them after computing busy intervals so you only offer slots within allowable windows.

    Representing busy intervals and computing free slots deterministically

    Represent busy intervals as [start, end) pairs in UTC or a normalized timezone. Merge overlapping busy intervals deterministically by sorting starts then coalescing. Subtract merged busy intervals from availability windows to compute free intervals. Doing this deterministically ensures reproducible slot results.

    Algorithm for merging busy intervals and deriving contiguous free blocks

    Sort intervals by start time. Initialize a current interval; iterate intervals and if the next overlaps or touches the current, merge by extending the end to the max end; otherwise, push the current and start a new one. After merging, compute gaps between availability window start/end and merged busy intervals to produce free blocks. Apply buffer and lead-time policies to those free blocks and then split them into booking-sized slots.

    Handling Edge Cases and Complex Calendar Scenarios

    Completely free days and how to represent all-day availability

    For completely free days, represent availability as the configured working hours (or full day if you allow all-day bookings). If you support all-day availability, present it as a set of contiguous slots spanning the working window, but still apply minimum lead time and maximum booking duration rules. Clearly convey availability to users as “open all day” or list representative slots.

    Fully booked days and returning an appropriate user-facing response

    When a day is fully booked and no free block remains (after buffers and lead time), send a clear, friendly voice response like “There are no available times on that day; would you like to try another day?” Avoid returning empty data silently; provide alternatives (next available day or allow waitlist).

    Recurring events, event transparency, and tentative events behavior

    Handle recurring events by expanding instances during your query window. Respect event transparency: if an event is marked transparent, it typically doesn’t block freebusy; if opaque, it does. For tentative events you may treat them as busy or offer them as lower-confidence blocks depending on your policy; determinism is key — decide and document how tentatives are treated.

    Cross-timezone bookings, daylight saving time transitions, and calendar locale issues

    Normalize all times to the calendar’s timezone and convert to the caller’s timezone for presentation. Be mindful of DST transitions: a slot that exists in UTC may shift in local time. Use timezone-aware libraries and always handle ambiguous times (fall back) and non-existent times (spring forward) by consistent rules and user-friendly messaging.

    Buffer Times, Minimum Lead Time, and Booking Policies

    Why buffer times and lead times matter for voicemail/voice bookings

    Buffers protect you from back-to-back bookings and give you prep and wind-down time; lead time prevents last-minute bookings you can’t handle. For voice-driven systems these are crucial because you might need time to verify identities, prepare resources, or ensure logistics.

    Implementing pre- and post-buffer around events

    Apply pre-buffer by extending busy intervals backward by the pre-buffer amount and post-buffer by extending forward. Do this before merging intervals so buffers coalesce with adjacent events. This prevents tiny gaps between events from appearing bookable.

    Configurable minimum lead time to prevent last-minute bookings

    Enforce a minimum lead time by removing any slots that start before now + leadTime. This is especially important in voice flows where confirmation and booking may take extra time. Make leadTime configurable per calendar or globally.

    Policy combinations (e.g., public slots vs private slots) and precedence rules

    Support multiple policy layers: global defaults, calendar-level settings, and per-event overrides (e.g., VIP-only). Establish clear precedence (e.g., explicit event-level blocks > calendar policies > global defaults) and document how conflicting policies are resolved. Ensure the deterministic checker evaluates policies in the same order every time.

    Designing the Deterministic n8n Workflow

    Workflow entry points and how voice AI triggers the availability check

    Expose an HTTP trigger node in n8n that Voice AI calls with the parsed intent. Ensure the payload includes caller timezone, desired date range, duration, and any constraints. Optionally, support an async callback URL if the check may take longer than the voice session allows.

    Key n8n nodes used: HTTP request, Function, IF, Set, SplitInBatches

    Use HTTP Request nodes to call Google APIs, Function or Code nodes to run your JS availability logic, IF nodes for branching on edge cases, Set nodes to normalize data, and SplitInBatches for iterating calendars or time ranges without overloading APIs. Keep the workflow modular and readable.

    State management inside the workflow and idempotency considerations

    Avoid relying on in-memory state across runs. For idempotency (e.g., holds and bookings), generate and persist deterministic IDs if you create temporary holds (a short-lived pending event with a unique idempotency key) so retries don’t create duplicates. Use external storage (a DB or calendar events with a known token) if you need cross-run state.

    Composing reusable subworkflows for calendar lookup, slot generation, and formatting

    Break the workflow into subworkflows: calendarLookup (calls freebusy/events), slotGenerator (merges intervals and generates slots), and formatter (creates voice-friendly messages). This lets you reuse these components for rescheduling, cancellation, and reporting.

    Code Node Implementation Details (JavaScript)

    Input and output contract for the Code (Function) node

    Design the Code node to accept a JSON payload: { calendarId, timeMin, timeMax, durationMinutes, timezone, buffers: , leadTimeMinutes, workingHours } and to return { slots: [], unavailableReason?, debug?: { mergedBusy:[], freeWindows:[] } }. Keep the contract strict and timezone-aware.

    Core functions: normalizeTimeRanges, mergeIntervals, generateSlots

    Implement modular functions:

    • normalizeTimeRanges converts inputs to a consistent timezone and format (ISO strings in UTC).
    • mergeIntervals coalesces overlapping busy intervals deterministically.
    • generateSlots subtracts busy intervals from working windows, applies buffers and lead time, and slices free windows into booking-sized slots.

    Include the functions so they’re unit-testable independently.

    Handling asynchronous Google Calendar API calls and retries

    In n8n, call Google APIs through HTTP Request nodes or via the Code node using fetch/axios. Implement retries with exponential backoff for transient 5xx or rate-limit 429 responses. Make API calls idempotent where possible. For batch calls like freebusy, pass all calendars at once to reduce calls.

    Unit-testable modular code structure and code snippets to include

    Organize code into pure functions with no external side effects so you can unit test them. Below is a compact example of the core JS functions you can include in the Code node or a shared library:

    // Example utility functions (simplified) function toMillis(iso) { return new Date(iso).getTime(); } function iso(millis) { return new Date(millis).toISOString(); }

    function normalizeTimeRanges(ranges, tz) { // Assume inputs are ISO strings; convert if needed. For demo, return as-is. return ranges.map(r => ({ start: new Date(r.start).toISOString(), end: new Date(r.end).toISOString() })); }

    function mergeIntervals(intervals) { if (!intervals || intervals.length === 0) return []; const sorted = intervals .map(i => ({ start: toMillis(i.start), end: toMillis(i.end) })) .sort((a,b) => a.start – b.start); const merged = []; let cur = sorted[0]; for (let i = 1; i

Social Media Auto Publish Powered By : XYZScripts.com