calendly-api
Calendly scheduling automation using REST API v2 for managing event types, availability, bookings, webhooks, and scheduling workflows
What this skill does
# Calendly API Skill
Master Calendly scheduling automation using the REST API v2. This skill covers event type management, availability configuration, booking workflows, webhook integrations, and automated scheduling patterns for building seamless meeting coordination.
## When to Use This Skill
### USE when:
- Automating interview scheduling workflows
- Building meeting booking integrations
- Creating round-robin scheduling systems
- Tracking scheduled events programmatically
- Integrating calendars with CRM systems
- Building appointment reminders
- Creating custom booking confirmation flows
- Automating follow-up sequences after meetings
- Syncing Calendly with external calendars
- Building scheduling analytics dashboards
### DON'T USE when:
- Simple calendar display (use Google Calendar API)
- Real-time video calls (use Zoom/Teams API)
- Complex resource scheduling (use specialized tools)
- Internal meeting coordination only (use calendar apps)
- One-off manual scheduling (use Calendly UI directly)
## Prerequisites
### Calendly API Setup
```bash
# 1. Get API credentials at https://calendly.com/integrations/api_webhooks
# 2. Create a Personal Access Token or OAuth app
# 3. Note: API v2 requires organization-level access for some endpoints
# Personal Access Token:
# - Go to Integrations > API & Webhooks
# - Generate a new token
# - Copy the token (shown only once)
# OAuth 2.0 App:
# - Go to https://developer.calendly.com/
# - Create an OAuth application
# - Configure redirect URIs
# - Note client_id and client_secret
# Required OAuth Scopes:
# - default - Basic access
# - organization:read - Read organization data
# - organization:write - Manage organization
# - user:read - Read user profiles
# - scheduling_link:read - Read scheduling links
# - event_type:read - Read event types
# - event_type:write - Manage event types
# - scheduled_event:read - Read scheduled events
# - scheduled_event:write - Manage scheduled events
# - invitee:read - Read invitee data
# - webhook:read - Read webhooks
# - webhook:write - Manage webhooks
```
### Python Environment Setup
```bash
# Create virtual environment
python -m venv calendly-env
source calendly-env/bin/activate # Linux/macOS
# calendly-env\Scripts\activate # Windows
# Install dependencies
pip install requests python-dotenv httpx aiohttp
# Create requirements.txt
cat > requirements.txt << 'EOF'
requests>=2.31.0
python-dotenv>=1.0.0
httpx>=0.25.0
aiohttp>=3.9.0
pydantic>=2.5.0
EOF
# Environment variables
cat > .env << 'EOF'
CALENDLY_API_KEY=your-personal-access-token
CALENDLY_CLIENT_ID=your-oauth-client-id
CALENDLY_CLIENT_SECRET=your-oauth-client-secret
CALENDLY_WEBHOOK_SECRET=your-webhook-signing-secret
EOF
```
### API Client Setup
```python
# client.py
# ABOUTME: Calendly API client with authentication
# ABOUTME: Handles requests, pagination, and error handling
import os
import requests
from typing import Optional, Dict, Any, List
from dotenv import load_dotenv
load_dotenv()
class CalendlyClient:
"""Calendly API v2 client"""
BASE_URL = "https://api.calendly.com"
def __init__(self, api_key: str = None):
self.api_key = api_key or os.environ.get("CALENDLY_API_KEY")
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
})
self._current_user = None
self._organization = None
def _request(
self,
method: str,
endpoint: str,
params: Dict = None,
json: Dict = None,
) -> Dict:
"""Make an API request"""
url = f"{self.BASE_URL}{endpoint}"
response = self.session.request(
method=method,
url=url,
params=params,
json=json,
)
if response.status_code == 429:
# Rate limited
retry_after = int(response.headers.get("Retry-After", 60))
raise Exception(f"Rate limited. Retry after {retry_after}s")
response.raise_for_status()
if response.status_code == 204:
return {}
return response.json()
def get(self, endpoint: str, params: Dict = None) -> Dict:
"""GET request"""
return self._request("GET", endpoint, params=params)
def post(self, endpoint: str, json: Dict = None) -> Dict:
"""POST request"""
return self._request("POST", endpoint, json=json)
def delete(self, endpoint: str) -> Dict:
"""DELETE request"""
return self._request("DELETE", endpoint)
def paginate(
self,
endpoint: str,
params: Dict = None,
key: str = "collection",
limit: int = None,
) -> List[Dict]:
"""Paginate through results"""
params = params or {}
params["count"] = 100
results = []
while True:
response = self.get(endpoint, params)
items = response.get(key, [])
results.extend(items)
if limit and len(results) >= limit:
return results[:limit]
pagination = response.get("pagination", {})
next_page_token = pagination.get("next_page_token")
if not next_page_token:
break
params["page_token"] = next_page_token
return results
@property
def current_user(self) -> Dict:
"""Get current user info (cached)"""
if not self._current_user:
response = self.get("/users/me")
self._current_user = response.get("resource")
return self._current_user
@property
def user_uri(self) -> str:
"""Get current user URI"""
return self.current_user["uri"]
@property
def organization_uri(self) -> str:
"""Get current organization URI"""
return self.current_user["current_organization"]
# Global client instance
client = CalendlyClient()
```
## Core Capabilities
### 1. User and Organization Management
```python
# users.py
# ABOUTME: User and organization management
# ABOUTME: Retrieve user profiles, organization info, memberships
from client import client
def get_current_user() -> dict:
"""Get the current authenticated user"""
response = client.get("/users/me")
user = response.get("resource", {})
return {
"uri": user.get("uri"),
"name": user.get("name"),
"email": user.get("email"),
"slug": user.get("slug"),
"scheduling_url": user.get("scheduling_url"),
"timezone": user.get("timezone"),
"organization": user.get("current_organization"),
}
def get_user_by_uri(user_uri: str) -> dict:
"""Get a user by their URI"""
# Extract UUID from URI
uuid = user_uri.split("/")[-1]
response = client.get(f"/users/{uuid}")
return response.get("resource", {})
def get_organization(organization_uri: str = None) -> dict:
"""Get organization details"""
org_uri = organization_uri or client.organization_uri
uuid = org_uri.split("/")[-1]
response = client.get(f"/organizations/{uuid}")
return response.get("resource", {})
def list_organization_memberships(
organization_uri: str = None,
email: str = None,
) -> list:
"""List organization memberships"""
org_uri = organization_uri or client.organization_uri
params = {"organization": org_uri}
if email:
params["email"] = email
return client.paginate("/organization_memberships", params=params)
def get_user_availability_schedules(user_uri: str = None) -> list:
"""Get user's availability schedules"""
user = user_uri or client.user_uri
params = {"user": user}
return client.paginate("/user_availability_schedules", params=params)
def get_user_busy_times(
user_uri: str = None,
start_timRelated in communication
miro-api
IncludedMiro whiteboard automation using REST API v2 and Python SDK for creating boards, frames, shapes, connectors, and collaborative visual workflows
slack-api
IncludedSlack bot development and workspace automation using Web API, Events API, Socket Mode, and Block Kit for building interactive messaging applications
teams-api
IncludedMicrosoft Teams automation using Graph API, Bot Framework, Adaptive Cards, and webhooks for enterprise messaging and collaboration
Customer Support Reply
IncludedCraft empathetic, effective customer support responses that solve problems
Press Release Writer
IncludedWrite professional press releases that get media attention and coverage
Internal Memo Creator
IncludedWrite clear, professional internal memos for company communication