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

# AI agents

> How AI agents can use the Cal.com API v2 to manage scheduling

This guide explains how to build AI agents that interact with Cal.com's scheduling infrastructure.

## Recommended: Use the Cal.com CLI

For agents that can execute commands on a machine, use the official Cal.com CLI instead of calling the API directly. The CLI handles authentication, versioning, and common workflows automatically.

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install -g @calcom/cli
    ```
  </Tab>

  <Tab title="curl">
    ```bash theme={null}
    curl -fsSL https://cal.com/install.sh | bash
    ```
  </Tab>
</Tabs>

The CLI includes `--help` flags on all commands to learn about available options:

```bash theme={null}
calcom --help
calcom bookings --help
calcom slots --help
```

<Note>
  Only fall back to the API approach below if your agent cannot install or execute the CLI on its machine.
</Note>

## Overview

Cal.com API v2 enables AI agents to:

* **Check availability** - Query available time slots for any user or team
* **Create bookings** - Schedule meetings on behalf of users
* **Manage event types** - Create and configure different meeting types
* **Handle rescheduling and cancellations** - Modify existing bookings
* **Manage schedules** - Set and update user availability
* **Track credit usage** - Check balances and charge credits for agent interactions

## Authentication

AI agents should authenticate using an **API key**. Generate one in [Settings → Developer → API Keys](https://app.cal.com/settings/developer/api-keys).

```bash theme={null}
curl -X GET "https://api.cal.com/v2/me" \
  -H "Authorization: Bearer cal_live_xxxxxxxxxxxx" \
  -H "cal-api-version: 2024-08-13"
```

<Warning>
  The `cal-api-version` header is required for all v2 endpoints. If you omit it, requests will return a 404. Always include `cal-api-version: 2024-08-13`.
</Warning>

## Common workflows

### 1. Check availability

Query available slots using username and event slug—no need to look up IDs first:

```bash theme={null}
curl -X GET "https://api.cal.com/v2/slots?username=bailey&eventSlug=15min&startTime=2024-01-15T00:00:00Z&endTime=2024-01-16T23:59:59Z" \
  -H "cal-api-version: 2024-08-13"
```

Response includes available time slots:

```json theme={null}
{
  "status": "success",
  "data": {
    "slots": {
      "2024-01-15": [
        { "time": "2024-01-15T09:00:00Z" },
        { "time": "2024-01-15T10:00:00Z" },
        { "time": "2024-01-15T14:00:00Z" }
      ]
    }
  }
}
```

### 2. Create a booking

Schedule a meeting using username and event slug. This is the most common pattern for AI agents that extract scheduling intent from natural language (e.g., "book 15min with bailey"):

```bash theme={null}
curl -X POST "https://api.cal.com/v2/bookings" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "eventTypeSlug": "15min",
    "username": "bailey",
    "start": "2024-01-15T09:00:00Z",
    "attendee": {
      "name": "John Doe",
      "email": "john@example.com",
      "timeZone": "America/New_York"
    }
  }'
```

<Note>
  The booking creation endpoint is public and does not require authentication. This allows agents to book on behalf of external users.
</Note>

### 3. Handle custom booking questions

Most Cal.com users have required questions on their booking pages (e.g., "What is this meeting about?"). If you omit required fields, the API returns a 400 error.

Include responses in `bookingFieldsResponses`:

```bash theme={null}
curl -X POST "https://api.cal.com/v2/bookings" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "eventTypeSlug": "consultation",
    "username": "bailey",
    "start": "2024-01-15T09:00:00Z",
    "attendee": {
      "name": "John Doe",
      "email": "john@example.com",
      "timeZone": "America/New_York"
    },
    "bookingFieldsResponses": {
      "notes": "Discussing the new AI integration",
      "company_size": "10-50"
    }
  }'
```

<Tip>
  To discover which fields are required, fetch the event type details first. The `bookingFields` array shows all custom questions and their requirements.
</Tip>

### 4. Instant bookings for urgent requests

For teams handling urgent requests, use the `instant` flag to bypass normal scheduling and immediately ring available team members:

```bash theme={null}
curl -X POST "https://api.cal.com/v2/bookings" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "eventTypeSlug": "urgent-support",
    "username": "support-team",
    "start": "2024-01-15T09:00:00Z",
    "instant": true,
    "attendee": {
      "name": "John Doe",
      "email": "john@example.com",
      "timeZone": "America/New_York"
    }
  }'
```

<Note>
  Instant bookings require the event type to be configured for instant meetings. This is ideal for AI agents routing urgent customer requests.
</Note>

### 5. Get user's event types

Retrieve available event types to offer booking options:

```bash theme={null}
curl -X GET "https://api.cal.com/v2/event-types?username=bailey" \
  -H "Authorization: Bearer cal_live_xxxxxxxxxxxx" \
  -H "cal-api-version: 2024-08-13"
```

### 6. Reschedule a booking

Move an existing booking to a new time:

```bash theme={null}
curl -X POST "https://api.cal.com/v2/bookings/{bookingUid}/reschedule" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "start": "2024-01-16T10:00:00Z",
    "rescheduleReason": "Attendee requested different time"
  }'
```

### 7. Cancel a booking

```bash theme={null}
curl -X POST "https://api.cal.com/v2/bookings/{bookingUid}/cancel" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "cancellationReason": "Meeting no longer needed"
  }'
```

## Credit management

If your AI agent runs on the Cal.com platform, you can track usage by checking and charging credits through the API. This is useful for metering agent interactions against your account's credit balance.

### Check available credits

Before performing a billable action, verify that the user or team has sufficient credits:

```bash theme={null}
curl -X GET "https://api.cal.com/v2/credits/available" \
  -H "Authorization: Bearer cal_live_xxxxxxxxxxxx" \
  -H "cal-api-version: 2024-08-13"
```

Response:

```json theme={null}
{
  "status": "success",
  "data": {
    "hasCredits": true,
    "balance": {
      "monthlyRemaining": 450,
      "additional": 200
    }
  }
}
```

The `balance` object breaks down your remaining credits:

* `monthlyRemaining` — credits included in your current billing cycle
* `additional` — purchased credits outside the monthly allowance

### Charge credits

After a completed agent interaction, charge the appropriate number of credits:

```bash theme={null}
curl -X POST "https://api.cal.com/v2/credits/charge" \
  -H "Authorization: Bearer cal_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "credits": 5,
    "creditFor": "AI_AGENT",
    "externalRef": "agent-thread-abc-1711432800000"
  }'
```

Response:

```json theme={null}
{
  "status": "success",
  "data": {
    "charged": true,
    "remainingBalance": {
      "monthlyRemaining": 445,
      "additional": 200
    }
  }
}
```

| Parameter | Required | Description |
| - | - | - |
| `credits` | Yes | Number of credits to charge (minimum 1) |
| `creditFor` | Yes | Usage type — use `AI_AGENT` for agent interactions |
| `externalRef` | No | Unique reference string for idempotency. Prevents double-charging if the same request is retried. |

<Tip>
  Always include an `externalRef` tied to your agent's conversation or thread ID. This prevents duplicate charges if a network retry sends the same request twice.
</Tip>

### Example: check-then-charge pattern

```typescript theme={null}
const headers = {
  "Authorization": "Bearer cal_live_xxxxxxxxxxxx",
  "Content-Type": "application/json",
  "cal-api-version": "2024-08-13"
};

// 1. Check credits before starting work
const available = await fetch("https://api.cal.com/v2/credits/available", { headers });
const { data } = await available.json();

if (!data.hasCredits) {
  throw new Error("No credits available");
}

// 2. Perform the agent interaction
const result = await runAgentTask();

// 3. Charge credits after completion
await fetch("https://api.cal.com/v2/credits/charge", {
  method: "POST",
  headers,
  body: JSON.stringify({
    credits: 5,
    creditFor: "AI_AGENT",
    externalRef: `thread-${threadId}-${Date.now()}`
  })
});
```

## Best practices for AI agents

### Handle time zones correctly

Always specify time zones explicitly. Store user preferences and pass them in requests:

```json theme={null}
{
  "attendee": {
    "timeZone": "Europe/London"
  }
}
```

### Implement retry logic

API requests may occasionally fail. Implement exponential backoff:

```typescript theme={null}
async function callWithRetry(fn: () => Promise<Response>, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fn();
      if (response.ok) return response;
      if (response.status === 429) {
        await sleep(Math.pow(2, i) * 1000);
        continue;
      }
      throw new Error(`API error: ${response.status}`);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await sleep(Math.pow(2, i) * 1000);
    }
  }
}
```

### Validate availability before booking

Always check slots before attempting to create a booking to avoid conflicts:

```typescript theme={null}
// 1. Get available slots
const slots = await getAvailableSlots("bailey", "15min", startDate, endDate);

// 2. Verify the desired slot is available
const isAvailable = slots.some(slot => slot.time === desiredTime);

// 3. Create booking only if slot is available
if (isAvailable) {
  await createBooking("bailey", "15min", desiredTime, attendee);
}
```

### Use webhooks for real-time updates

Configure webhooks to receive notifications when bookings are created, rescheduled, or cancelled:

```bash theme={null}
curl -X POST "https://api.cal.com/v2/webhooks" \
  -H "Authorization: Bearer cal_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "cal-api-version: 2024-08-13" \
  -d '{
    "subscriberUrl": "https://your-agent.com/webhooks/cal",
    "eventTriggers": ["BOOKING_CREATED", "BOOKING_RESCHEDULED", "BOOKING_CANCELLED"],
    "active": true
  }'
```

## Discover the API from a booking page

Cal.com web app pages, including personal, team and organization booking pages, send a `Link` header that points agents to the API:

```bash theme={null}
curl -sI "https://cal.com/bailey/15min" | grep -i "^link"
```

| Relation | Points to |
| - | - |
| `api-catalog` | `/.well-known/api-catalog` on the same host, which lists the API v2 and the hosted [MCP server](/docs/mcp-server) |
| `service-desc` | The API v2 OpenAPI description (JSON) |
| `service-doc` | The [API v2 reference](/docs/api-reference/v2/introduction) |

Discovery documents under `/.well-known/` also work on organization domains such as `acme.cal.com`. They are served as discovery documents, not treated as organization booking pages.

### OAuth protected-resource metadata

Each origin serves OAuth protected-resource metadata ([RFC 9728](https://www.rfc-editor.org/rfc/rfc9728)) for the page you are on. `/.well-known/oauth-protected-resource` names the origin itself as the resource. To get metadata for a specific page, add its path after the metadata path:

```bash theme={null}
curl "https://acme.cal.com/.well-known/oauth-protected-resource/bailey/15min"
```

```json theme={null}
{
  "resource": "https://acme.cal.com/bailey/15min",
  "authorization_servers": ["https://cal.com"],
  "scopes_supported": ["EVENT_TYPE_READ", "EVENT_TYPE_WRITE", "BOOKING_READ", "..."],
  "bearer_methods_supported": ["header"],
  "resource_documentation": "https://cal.com/docs/api-reference/v2/introduction"
}
```

The response lists the Cal.com OAuth authorization server, the supported scopes and the API documentation. The API keeps its own metadata at `https://api.cal.com/.well-known/oauth-protected-resource`, which the API catalog links to.

## Booking page tools for in-browser agents

Cal.com booking pages register [WebMCP](https://github.com/webmachinelearning/webmcp) tools when the visitor's browser supports WebMCP (`document.modelContext`). An agent running in the browser can use them to read the event and pick a time without scraping the page.

| Tool | Input | Description |
| - | - | - |
| `get_event_details` | None | Returns the event title, duration in minutes and the visitor's time zone |
| `list_available_times` | `date` (optional, `YYYY-MM-DD`) | Lists available start times for the dates currently loaded in the calendar, in the visitor's time zone. With a `date`, returns that date only; without one, returns up to the first seven loaded dates that have availability. Out-of-office times are excluded. |
| `select_time` | `time` (required, ISO start time) | Selects one of the currently loaded available times and opens the booking form, just like clicking the time on the page |

Each tool returns its result as JSON text.

<Note>
  `select_time` never creates a booking. The visitor still has to fill in the booking form and confirm. It declines, and asks for the time to be picked on the page, when the event asks the booker to propose several times or when picking a time would book straight away (for example, because every required booking question is already prefilled).
</Note>

## iMessage RSVPs from a linked phone number

When a Cal Event offers **Register with iMessage**, a guest can RSVP by texting from their phone instead of filling in the form. If the guest's phone number is linked to a Cal.com account through the Cal.com assistant on iMessage, an RSVP made while signed out of Cal.com is saved to that account, the same as an RSVP made while signed in. It shows on the event page when they sign in.

To link a number, message the Cal.com assistant on iMessage, open the link it replies with, and select **Connect account** while signed in to Cal.com.

<Note>
  If the RSVP is started from the event page while signed in, it's saved to the signed-in account, even when the phone number is linked to a different account. An RSVP from a number that no account has linked or [verified on its profile](/docs/features/phone-rsvp) stays anonymous. A number verified on a profile takes priority over an iMessage link.
</Note>

## Rate limits

API key authentication allows **120 requests per minute** by default. Contact support if you need higher limits for production agents.

## API reference

For complete endpoint documentation, see the [API v2 Reference](/docs/api-reference/v2/introduction).

Key endpoints for agents:

| Endpoint | Description |
| - | - |
| `GET /v2/slots` | Check available time slots |
| `POST /v2/bookings` | Create a new booking |
| `POST /v2/bookings/:uid/reschedule` | Reschedule a booking |
| `POST /v2/bookings/:uid/cancel` | Cancel a booking |
| `GET /v2/event-types` | List event types |
| `GET /v2/schedules` | Get user schedules |
| `POST /v2/webhooks` | Configure webhooks |
| `GET /v2/credits/available` | Check credit balance |
| `POST /v2/credits/charge` | Charge credits for usage |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.