> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telli.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect your calendar

> Connect a calendar provider so your telli agent can check availability and book appointments during calls.

<Tabs>
  <Tab title="Overview">
    When you connect a calendar, your voice AI agent can:

    * **Check availability** See open time slots in real-time during calls
    * **Book appointments** Schedule meetings without any manual intervention
    * **Collect information** Gather booking details from callers or your CRM

    Each agent can have its own calendar connection, so different workflows can book different meeting types or route to different teams.
  </Tab>

  <Tab title="Supported Providers">
    telli supports five main calendar integrations:

    | **Provider**            | **Best For**                                                   |
    | ----------------------- | -------------------------------------------------------------- |
    | **Calendly**            | Teams already using Calendly with complex booking forms        |
    | **Zeeg**                | Teams using Zeeg scheduling pages and custom invitee questions |
    | **Cal.com**             | Teams using Cal.com for scheduling                             |
    | **HubSpot Meetings**    | HubSpot users who book through HubSpot                         |
    | **Custom Calendar API** | Companies with their own scheduling system                     |
  </Tab>
</Tabs>

***

## Getting Started

<Steps>
  <Step title="Open Your Agent">
    1. Log in to the telli app
    2. Navigate to **Agents** in the sidebar
    3. Select the agent you want to configure
    4. Scroll to the **Calendar Integration** section
  </Step>

  <Step title="Choose Your Provider">
    Click the **Select Integration Type** dropdown to see available options:

    * **Calendly** For Calendly users
    * **Zeeg** For Zeeg users
    * **Cal.com** For Cal.com users
    * **HubSpot** For HubSpot Meetings users
    * **Generic Calendar** For custom API connections
  </Step>
</Steps>

***

## Provider Setup

<Tabs>
  <Tab title="Calendly">
    <Tip>
      **When to Use**

      * Your team already uses Calendly
      * You have custom booking questions on your event types
      * You want to automatically populate form fields from caller data
      * Different agents should book different meeting types
    </Tip>

    ### Fields Required

    | **Field**          | **Description**                                        |
    | ------------------ | ------------------------------------------------------ |
    | **API Key**        | Your Calendly API key                                  |
    | **Event Type URI** | The Calendly event type to use (e.g., `johndoe/30min`) |
    | **External URL**   | (Optional) Your Calendly booking page URL              |
    | **Booking Fields** | Mappings for custom questions on your event type       |

    ### Booking Fields

    You can map how each question on your Calendly form gets answered:

    | **Source Type**      | **How It Works**                                    | **When to Use**                                     |
    | -------------------- | --------------------------------------------------- | --------------------------------------------------- |
    | **Constant**         | Fixed value every time                              | Company name, internal notes, team name             |
    | **Contact Property** | Pulled from the caller's contact record in your CRM | Email, phone, company, first/last name              |
    | **System Variable**  | Resolved from internal data                         | Contact ID, timezone, account tier                  |
    | **LLM Parameter**    | Agent asks the caller during the call               | Meeting topic, preferred language, special requests |

    <Warning>
      Every required custom question on your Calendly event type must have a mapping configured, or the booking will fail. Optional questions without a mapping are simply skipped.
    </Warning>

    ### Setup Steps

    <Steps>
      <Step title="Open your agent in telli" />

      <Step title="Go to Calendar Integration → select Calendly" />

      <Step title="Enter your Calendly API key" />

      <Step title="Enter your event type URI (from your Calendly link)" />

      <Step title="Configure booking field mappings for each required question" />

      <Step title="Click Save" />
    </Steps>

    ### Finding Your Event Type URI

    Your Calendly event link looks like:

    ```text theme={null}
    https://calendly.com/johndoe/30min-call
    ```

    The URI is: `johndoe/30min-call`
  </Tab>

  <Tab title="Zeeg">
    <Tip>
      **When to Use**

      * Your team already uses Zeeg
      * You want to book against existing Zeeg scheduling pages
      * You have custom invitee questions on your scheduling pages
      * Different agents should book different meeting types
    </Tip>

    ### Fields Required

    | **Field**           | **Description**                                                                                            |
    | ------------------- | ---------------------------------------------------------------------------------------------------------- |
    | **API Key**         | Your Zeeg API token (created in [Account Settings → API](https://app.zeeg.me/account/settings/api-access)) |
    | **Scheduling Page** | The Zeeg scheduling page the agent should use for availability and booking                                 |
    | **Duration**        | The meeting length, picked from the durations your scheduling page exposes                                 |
    | **Location**        | Where the meeting happens, picked from the supported locations on your scheduling page                     |
    | **Booking Fields**  | Mappings for the custom invitee questions on your scheduling page                                          |

    ### Booking Fields

    You can map how each custom invitee question on your Zeeg scheduling page gets answered:

    | **Source Type**      | **How It Works**                                    | **When to Use**                                     |
    | -------------------- | --------------------------------------------------- | --------------------------------------------------- |
    | **Constant**         | Fixed value every time                              | Company name, internal notes, team name             |
    | **Contact Property** | Pulled from the caller's contact record in your CRM | Email, phone, company, first/last name              |
    | **System Variable**  | Resolved from internal data                         | Contact ID, timezone, account tier                  |
    | **LLM Parameter**    | Agent asks the caller during the call               | Meeting topic, preferred language, special requests |

    <Warning>
      Every required custom question on your Zeeg scheduling page must have a mapping configured, or the booking will fail. Optional questions without a mapping are simply skipped.
    </Warning>

    <Note>
      Zeeg's availability and booking API endpoints require an active paid Zeeg subscription.
    </Note>

    ### Setup Steps

    <Steps>
      <Step title="Open your agent in telli" />

      <Step title="Go to Calendar Integration → select Zeeg" />

      <Step title="Enter your Zeeg API token telli then loads the scheduling pages available to that token" />

      <Step title="Select the scheduling page the agent should use" />

      <Step title="Pick a duration and location from the options your scheduling page exposes" />

      <Step title="Configure booking field mappings for each required custom question" />

      <Step title="Click Save" />
    </Steps>

    ### Creating Your Zeeg API Token

    1. Sign in to Zeeg and open [Account Settings → API](https://app.zeeg.me/account/settings/api-access)
    2. Create a new token with these scopes:
       * `events:read` read scheduling pages and their custom invitee questions
       * `timetable` read available time slots for the selected scheduling page
       * `booking` create the booked Zeeg event during the call
    3. Copy the token and paste it into the API Key field in telli
  </Tab>

  <Tab title="Cal.com">
    <Tip>
      **When to Use**

      * Your team uses Cal.com for scheduling
      * You need agent-specific routing (different agents → different event types)
      * You want the flexibility of Cal.com's open-source platform
    </Tip>

    ### Fields Required

    | **Field**      | **Description**               |
    | -------------- | ----------------------------- |
    | **API Key**    | Your Cal.com API key          |
    | **Event Type** | The Cal.com event type to use |

    ### Setup Steps

    <Steps>
      <Step title="Open your agent in telli" />

      <Step title="Go to Calendar Integration → select Cal.com" />

      <Step title="Enter your Cal.com API key" />

      <Step title="Enter the event type slug" />

      <Step title="Click Save" />
    </Steps>

    ### Finding Your Event Type

    Your Cal.com event link looks like:

    ```text theme={null}
    https://cal.com/johndoe/30min
    ```

    The event type is: `30min`
  </Tab>

  <Tab title="HubSpot Meetings">
    <Tip>
      **When to Use**

      * Your team uses HubSpot for sales and scheduling
      * You want bookings to automatically create HubSpot records
      * You need meetings tied directly to your HubSpot CRM
    </Tip>

    ### Fields Required

    | **Field**             | **Description**                        |
    | --------------------- | -------------------------------------- |
    | **Access Token**      | Your HubSpot private app access token  |
    | **Meeting Link Slug** | The slug from your HubSpot meeting URL |
    | **Meeting Duration**  | Duration in minutes (e.g., `30`)       |

    ### Setup Steps

    <Steps>
      <Step title="Open your agent in telli" />

      <Step title="Go to Calendar Integration → select HubSpot" />

      <Step title="Enter your HubSpot private app access token" />

      <Step title="Enter your meeting link slug (e.g., johndoe/30min-call)" />

      <Step title="Enter the meeting duration in minutes" />

      <Step title="Click Save" />
    </Steps>

    ### Finding Your Meeting Link Slug

    1. Go to HubSpot's [Meetings Scheduler](https://meetings.hubspot.com/)
    2. Open the meeting you want to use
    3. Copy the meeting URL it looks like:

    ```text theme={null}
    https://meetings.hubspot.com/johndoe/30min-call
    ```

    4. The **slug** is everything after `meetings.hubspot.com/`: `johndoe/30min-call`

    ### Creating a HubSpot Private App

    1. In HubSpot, go to **Settings** → **Integrations** → **Private Apps**
    2. Click **Create a private app**
    3. Give it a name (e.g., `telli Integration`)
    4. Go to the **Scopes** tab
    5. Add these scopes:
       * `crm.objects.contacts.write`
       * `crm.schemas.contacts.write`
       * `scheduler.meetings.meeting-link.read`
       * `tickets`
    6. Click **Create**
    7. Copy the access token (shown once save it securely)
    8. Use this token in telli
  </Tab>

  <Tab title="Custom Calendar API">
    <Tip>
      **When to Use**

      * You have your own scheduling system
      * You need full control over the booking logic
      * You're not using any of the supported third-party tools
      * You want to integrate with an internal booking system
    </Tip>

    ### Fields Required

    | **Field**                | **Description**                                      |
    | ------------------------ | ---------------------------------------------------- |
    | **Available Slots URL**  | Your API endpoint to fetch available appointments    |
    | **Book Appointment URL** | (Optional) Your API endpoint to book a selected slot |

    ### Setup Steps

    <Steps>
      <Step title="Open your agent in telli" />

      <Step title="Go to Calendar Integration → select Generic Calendar" />

      <Step title="Enter your Available Slots URL (required)" />

      <Step title="Enter your Book Appointment URL (optional leave blank for availability-only)" />

      <Step title="Click Save" />
    </Steps>

    ### Implementation Notes

    * Use **UTC timestamps** in ISO 8601 format
    * Return **HTTP 200** responses with success/failure in the body
    * Make sure your endpoints are **publicly reachable** by telli
    * The `start_iso` field is used as the slot identifier for bookings

    <AccordionGroup>
      <Accordion title="API Specification">
        #### Get Available Slots

        **Request:**

        ```json theme={null}
        POST https://your-api.com/available

        {
          "contact_id": "telli contact identifier",
          "external_contact_id": "your internal contact ID",
          "contact_details": {
            "email": "caller@example.com",
            "name": "John Doe"
          }
        }
        ```

        **Response:**

        ```json theme={null}
        {
          "available": [
            {
              "start_iso": "2024-01-02T14:00:00.000Z",
              "end_iso": "2024-01-02T14:30:00.000Z"
            },
            {
              "start_iso": "2024-01-02T15:00:00.000Z",
              "end_iso": "2024-01-02T15:30:00.000Z"
            }
          ]
        }
        ```

        #### Book Appointment

        **Request:**

        ```json theme={null}
        POST https://your-api.com/book

        {
          "contact_id": "telli contact identifier",
          "external_contact_id": "your internal contact ID",
          "start_iso": "2024-01-02T14:00:00.000Z",
          "contact_details": {
            "email": "caller@example.com",
            "name": "John Doe"
          }
        }
        ```

        **Success Response:**

        ```json theme={null}
        {
          "status": "success"
        }
        ```

        **Failure Response:**

        ```json theme={null}
        {
          "status": "failed",
          "reason": "Appointment slot is no longer available"
        }
        ```
      </Accordion>

      <Accordion title="Authentication">
        Requests from telli include a signature header you can verify:

        ```javascript theme={null}
        const crypto = require("crypto");

        function verifyRequest(payload, signature, apiKey) {
          const expectedSignature = crypto
            .createHmac("sha256", apiKey)
            .update(JSON.stringify(payload))
            .digest("hex");

          return signature === expectedSignature;
        }
        ```

        Check the `x-telli-signature` header on incoming requests.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

***

<Tabs>
  <Tab title="Per-Agent Configuration">
    <Info>
      Each agent can have its own calendar connection. This is powerful for:

      * Different teams with different calendars
      * Different sales motions (demo calls vs. discovery vs. support)
      * Routing to specific reps or departments
      * A/B testing different scheduling flows

      Simply configure the calendar integration separately for each agent.
    </Info>
  </Tab>

  <Tab title="Example">
    Once connected, your agent can handle scheduling conversations like this:

    * **Caller:** "I'd like to schedule a demo"
    * **Agent:** "Let me check availability" → calls your calendar
    * **Agent:** "I have Tuesday at 2pm or Wednesday at 10am which works?"
    * **Caller:** "Tuesday please"
    * **Agent:** Books the slot and confirms the appointment

    The entire interaction is hands-free.
  </Tab>

  <Tab title="Troubleshooting">
    | **Issue**                | **Solution**                                                 |
    | ------------------------ | ------------------------------------------------------------ |
    | Booking fails            | Check that all required booking fields are mapped (Calendly) |
    | No available slots shown | Verify your API credentials and endpoints are correct        |
    | HubSpot booking fails    | Ensure your private app has all required scopes              |
    | Authentication errors    | For custom APIs, verify your signature verification logic    |
  </Tab>
</Tabs>
