docs/api-reference/v2/migration-guide.mdx
This guide will help you migrate your integration from Cal.com API V1 to V2. The V2 API offers improved performance, enhanced security, better response objects, and new features that make it easier to build powerful integrations.
In V1, you authenticated using an API key in the query string:
curl https://api.cal.com/v1/event-types?apiKey=cal_test_xxxxxx
In V2, authentication uses header-based API keys for improved security:
curl https://api.cal.com/v2/event-types \
-H "Authorization: Bearer cal_live_xxxxxx"
| Version | Base URL |
|---|---|
| V1 | https://api.cal.com/v1 |
| V2 | https://api.cal.com/v2 |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
POST /bookings | POST /v2/bookings | Enhanced response object with more booking details |
GET /bookings/{id} | GET /v2/bookings/{uid} | Returns richer booking information |
DELETE /bookings/{id} | POST /v2/bookings/{uid}/cancel | Now uses POST with cancellation reason support |
PATCH /bookings/{id} | POST /v2/bookings/{uid}/reschedule | Rescheduling is now a dedicated endpoint |
V1 example:
DELETE /v1/bookings/123?apiKey=cal_test_xxx
V2 example:
POST /v2/bookings/cal_abc123/cancel
Authorization: Bearer cal_live_xxx
Content-Type: application/json
{
"cancellationReason": "Schedule conflict"
}
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /event-types | GET /v2/event-types | Improved filtering and pagination |
POST /event-types | POST /v2/event-types | Enhanced configuration options |
GET /event-types/{id} | GET /v2/event-types/{id} | More detailed response |
DELETE /event-types/{id} | DELETE /v2/event-types/{id} | Same functionality |
PATCH /event-types/{id} | PATCH /v2/event-types/{id} | More update options available |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /schedules | GET /v2/schedules | Better structured response |
POST /schedules | POST /v2/schedules | Simplified schedule creation |
GET /schedules/{id} | GET /v2/schedules/{id} | Enhanced availability details |
DELETE /schedules/{id} | DELETE /v2/schedules/{id} | Same functionality |
PATCH /schedules/{id} | PATCH /v2/schedules/{id} | More flexible updates |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /users | GET /v2/me | Now returns authenticated user profile |
GET /users/{id} | GET /v2/me | User-specific endpoint for own profile |
PATCH /users/{id} | PATCH /v2/me | Update your own profile |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /teams | GET /v2/teams | Enhanced team information |
POST /teams | POST /v2/teams | More configuration options |
GET /teams/{id} | GET /v2/teams/{id} | Richer team details |
DELETE /teams/{id} | DELETE /v2/teams/{id} | Same functionality |
PATCH /teams/{id} | PATCH /v2/teams/{id} | More update options |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /webhooks | GET /v2/webhooks | Better webhook management |
POST /webhooks | POST /v2/webhooks | More event types available |
GET /webhooks/{id} | GET /v2/webhooks/{id} | Enhanced webhook details |
DELETE /webhooks/{id} | DELETE /v2/webhooks/{id} | Same functionality |
PATCH /webhooks/{id} | PATCH /v2/webhooks/{id} | More configuration options |
| V1 Endpoint | V2 Endpoint | Changes |
|---|---|---|
GET /slots/available | GET /v2/slots/available | Improved slot calculation and response format |
| N/A | POST /v2/slots/reserve | New: Reserve slots before booking |
| N/A | DELETE /v2/slots/reserve/{uid} | New: Release reserved slots |
V2 introduces comprehensive organization endpoints for enterprise customers:
GET /v2/orgs/teams - Manage organization teamsGET /v2/orgs/users - Manage organization usersGET /v2/orgs/bookings - View all organization bookingsGET /v2/orgs/memberships - Manage team membershipsGET /v2/orgs/roles - Manage custom roles and permissionsPOST /v2/bookings/{uid}/confirm - Confirm pending bookingsPOST /v2/bookings/{uid}/decline - Decline booking requestsPOST /v2/bookings/{uid}/mark-absent - Mark no-showsPOST /v2/bookings/{uid}/reassign - Reassign bookings to different hostsPOST /v2/bookings/{uid}/guests - Add guests to existing bookingsGET /v2/calendars - List connected calendarsGET /v2/calendars/busy-times - Check availability across calendarsPOST /v2/calendars/connect - Connect calendar providersPOST /v2/calendars/disconnect - Disconnect calendarsGET /v2/conferencing - List conferencing appsPOST /v2/conferencing/connect - Connect conferencing providersPOST /v2/conferencing/set-default - Set default conferencing app{
"booking": {
"id": 123,
"title": "Meeting",
"startTime": "2024-01-15T10:00:00Z"
}
}
{
"status": "success",
"data": {
"id": 123,
"uid": "cal_abc123xyz",
"title": "Meeting",
"startTime": "2024-01-15T10:00:00.000Z",
"endTime": "2024-01-15T11:00:00.000Z",
"status": "accepted",
"attendees": [...],
"metadata": {...}
}
}
Key improvements:
status and data wrapper{
"message": "Event type not found"
}
{
"status": "error",
"error": {
"code": "NOT_FOUND",
"message": "Event type not found",
"details": {
"eventTypeId": 123
}
}
}
V2 provides:
| Authentication Method | V1 Rate Limit | V2 Rate Limit |
|---|---|---|
| API Key | 120 req/min | 120 req/min |
V1:
const response = await fetch(
'https://api.cal.com/v1/bookings?apiKey=cal_test_xxx',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
eventTypeId: 123,
start: '2024-01-15T10:00:00Z',
responses: {
name: 'John Doe',
email: '[email protected]'
}
})
}
);
V2:
const response = await fetch(
'https://api.cal.com/v2/bookings',
{
method: 'POST',
headers: {
'Authorization': 'Bearer cal_live_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
eventTypeId: 123,
start: '2024-01-15T10:00:00.000Z',
attendee: {
name: 'John Doe',
email: '[email protected]',
timeZone: 'America/New_York'
}
})
}
);
const data = await response.json();
if (data.status === 'success') {
console.log('Booking created:', data.data);
}
V1:
import requests
response = requests.get(
'https://api.cal.com/v1/event-types',
params={'apiKey': 'cal_test_xxx'}
)
event_types = response.json()['event_types']
V2:
import requests
response = requests.get(
'https://api.cal.com/v2/event-types',
headers={'Authorization': 'Bearer cal_live_xxx'}
)
data = response.json()
if data['status'] == 'success':
event_types = data['data']
If you encounter issues during migration:
Start your migration today to ensure a smooth transition and take advantage of V2's enhanced capabilities.