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

# Component: scheduling_embed

> Embed your Calendly booking page in the conversation and get a webhook when the meeting is booked.

**`scheduling_embed`** renders your Calendly booking page inside the conversation. The user books a slot in the real widget, and the confirmed booking is reported to the PAL and delivered to your webhook as a `canvas.interaction` event.

See [Enabling and configuring components](/sections/conversational-video-interface/magic-canvas/components#enabling-and-configuring-components) for skill attachment and general component settings.

## Configuration

Attaching the skill alone does not activate `scheduling_embed`. It stays inactive (no action is compiled, no error) until a valid `scheduling_url` is saved in the skill config.

```bash theme={null}
curl -X PUT https://tavusapi.com/v2/pals/{pal_id}/skills/magic_canvas \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{
    "config": {
      "components": {
        "scheduling_embed": {
          "provider": "calendly",
          "scheduling_url": "https://calendly.com/your-team/30min"
        }
      }
    }
  }'
```

| Field            | Type    | Required | Description                                                                                                                                  |
| ---------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`       | string  | ❌        | Defaults to `"calendly"`, the only supported provider.                                                                                       |
| `scheduling_url` | string  | ✅        | Your HTTPS booking link, max 2048 characters (enforced when you save the config). The component activates as soon as a valid value is saved. |
| `enabled`        | boolean | ❌        | Defaults to `true`. Set `false` to switch the component off without deleting your link config.                                               |

<Warning>
  `scheduling_url` is validated on save: it must start with `https://`, be at
  most 2048 characters, and not point at localhost, cloud metadata hostnames,
  or private, loopback, link-local, or reserved IPs. No DNS
  resolution is performed, so other non-public hostnames can pass. The renderer
  also requires a `calendly.com` or `*.calendly.com` host; otherwise the card
  renders a "Scheduling not configured" panel.
</Warning>

## Arguments

The PAL invokes `canvas_show_scheduling_embed` when the user should book a meeting and a scheduling link is configured. The booking link itself is never an argument.

| Field           | Type   | Required | Description                                                  |
| --------------- | ------ | -------- | ------------------------------------------------------------ |
| `title`         | string | ❌        | Heading shown above the embed. 1–160 characters.             |
| `prefill`       | object | ❌        | Pre-populates the booking form. No extra keys allowed.       |
| `prefill.name`  | string | ❌        | Invitee name, filled into the widget. Up to 160 characters.  |
| `prefill.email` | string | ❌        | Invitee email, filled into the widget. Up to 254 characters. |

```json theme={null}
{
  "title": "Book a time",
  "prefill": {
    "name": "Ada Lovelace",
    "email": "ada@example.com"
  }
}
```

The runtime attaches a `layout` (`preferred_slot`) control. `scheduling_embed` renders inline in a side rail (default `safe-area-right`; the model may pick `safe-area-left` or `safe-area-right`) and supports live updates via `update_component`.

<Note>
  There is no `url`, `link`, or `scheduling_url` argument. The link comes from
  your PAL config, delivered directly to the sandboxed renderer, bypassing
  the model entirely.
</Note>

## Interactions

The built-in card emits exactly one interaction type: `submit`, sent when the user completes a booking. There is no close control, so closing the card without booking produces no interaction. Renderer failures surface as an in-card "Scheduling unavailable" panel, not as webhooks.

<Note>
  The interactions API also accepts `skip`, `dismiss`, `clear`, `error`, and
  `heartbeat` for this component, for custom clients that post their own
  interactions; these are not shape-validated by Tavus.
</Note>

### `submit`

The `value` object accepts only these keys:

| Field         | Type    | Required | Description                                                                                                                                                                                                            |
| ------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`    | string  | ✅        | Always `"calendly"`.                                                                                                                                                                                                   |
| `scheduled`   | boolean | ✅        | Always `true`; a submit only fires on a confirmed booking.                                                                                                                                                             |
| `event_uri`   | string  | ❌        | Calendly API resource URI (HTTPS, `calendly.com` or `*.calendly.com` host). Use with the Calendly API to fetch the meeting time, invitee answers, and cancellation links; Tavus passes it through without fetching it. |
| `invitee_uri` | string  | ❌        | Calendly API resource URI (HTTPS, `calendly.com` or `*.calendly.com` host). Passed through without being fetched.                                                                                                      |

Example webhook for a completed booking:

```json [expandable] theme={null}
{
  "message_type": "canvas",
  "event_type": "canvas.interaction",
  "properties": {
    "conversation_id": "c7f8a1b2c3d4",
    "interaction_id": "ci_call_9d41f2_submit_6f1c9a2e-3b7d-4e8a-9c01-5a2b8d7e4f10",
    "tool_call_id": "call_9d41f2",
    "component": "canvas.scheduling_embed",
    "component_version": "v1",
    "type": "submit",
    "value": {
      "provider": "calendly",
      "scheduled": true,
      "event_uri": "https://api.calendly.com/scheduled_events/GBGBDCAADAEDCRZ2",
      "invitee_uri": "https://api.calendly.com/scheduled_events/GBGBDCAADAEDCRZ2/invitees/AAAAAAAAAAAAAAAA"
    },
    "metadata": {
      "client_timestamp": "2026-06-09T18:42:11.000Z"
    },
    "created_at": "2026-06-09T18:42:11.123456"
  }
}
```

`created_at` is a naive ISO-8601 timestamp with microsecond precision and no timezone suffix.

The `canvas.interaction` webhook [fires once per interaction](/sections/conversational-video-interface/magic-canvas/api/interactions). Fetch the full history at any time:

```bash theme={null}
curl https://tavusapi.com/v2/conversations/{conversation_id}/canvas/interactions \
  -H "x-api-key: <your-api-key>"
```

## When to Use

Use `scheduling_embed` when booking a meeting is a goal of the conversation. The user books in your real Calendly page, so availability, routing, and confirmation emails work as they do on your website. For a date or time preference without a real booking, use [`calendar`](/sections/conversational-video-interface/magic-canvas/components/calendar) instead.
