Get Cal.com up and running and receive your first booking in minutes. This guide covers both Cal.com Cloud and self-hosted deployments.
New to Cal.com? This quickstart focuses on getting you productive quickly. For detailed installation options, see the Installation guide .
Choose your path
Sign up for an account
Visit cal.com/signup and create your account with email or OAuth. // Authentication uses NextAuth.js with multiple providers
// From apps/web/pages/api/auth/[...nextauth].tsx
providers : [
EmailProvider ,
GoogleProvider ,
GitHubProvider ,
// ... more providers
]
Use Continue with Google for faster setup - it will automatically connect your Google Calendar.
Complete your profile
Set your:
Username : Your booking URL will be cal.com/your-username
Name : Displayed on your booking page
Time zone : Ensures accurate availability
Bio (optional): Introduce yourself to bookers
// User profile structure from packages/prisma/schema.prisma:77
model User {
username String ? @ unique
name String ?
bio String ?
timeZone String @ default ( "Europe/London" )
weekStart String @ default ( "Sunday" )
}
Create your first event type
Cal.com creates a default “30 Minute Meeting” for you, but let’s customize it:
Go to Event Types in the sidebar
Click your “30 Minute Meeting” event
Customize the settings:
Title : What people see (e.g., “Quick Chat”)
URL : Your booking link slug (e.g., cal.com/you/quick-chat)
Duration : Meeting length (15, 30, 60 minutes, or custom)
Location : Where you’ll meet
Event type configuration options
// Core event type fields from packages/platform/types/event-types
{
title : "30 Minute Meeting" ,
slug : "30min" ,
lengthInMinutes : 30 ,
// Choose meeting location
locations : [
{ type: "zoom" }, // Zoom (requires integration)
{ type: "phone" }, // Phone call
{ type: "userPhone" }, // Booker provides phone
{ type: "integrations:google:meet" }, // Google Meet
{ type: "link" , link: "https://..." } // Custom link
],
// Booking rules
minimumBookingNotice : 120 , // 2 hours minimum notice
beforeEventBuffer : 15 , // 15 min buffer before
afterEventBuffer : 10 , // 10 min buffer after
// Advanced options
requiresConfirmation : false , // Auto-confirm or manual approval
disableGuests : false , // Allow/disallow additional guests
}
Click Save when done
Connect your calendar
Prevent double-bookings by connecting your calendar: Google Calendar
Outlook/Office 365
Apple Calendar
Click Apps in the sidebar
Find “Google Calendar” and click Connect
Sign in and grant permissions
Select which calendars to check for conflicts
// Google Calendar integration from apps/api/v2/src/ee/calendars
// Requires Google OAuth 2.0 credentials configured
{
GOOGLE_API_CREDENTIALS : {
web : {
client_id : "..." ,
client_secret : "..." ,
redirect_uris : [ "https://cal.com/api/integrations/googlecalendar/callback" ]
}
}
}
Click Apps in the sidebar
Find “Office 365 Calendar” and click Connect
Sign in with your Microsoft account
Grant calendar permissions
Click Apps in the sidebar
Find “Apple Calendar” and click Connect
Enter your Apple ID email
Use an app-specific password
Apple Calendar uses CalDAV. No API credentials needed - users connect individually.
Important : Connected calendars are checked for conflicts. Any busy events will block those time slots from being booked.
Set your availability
Define when you’re available for bookings:
Go to Availability in the sidebar
Edit your “Working Hours” schedule
Set your typical availability:
Days : Select working days
Time ranges : Add multiple time blocks per day
Time zone : Already set from your profile
// Schedule structure from packages/prisma/schema.prisma:534
model Schedule {
name String
timeZone String ?
availability : [
{
days: [ 1 , 2 , 3 , 4 , 5 ], // Monday-Friday (0=Sunday)
startTime: "09:00" , // 9 AM
endTime: "17:00" // 5 PM
}
]
}
Advanced availability options
Multiple schedules : Create different schedules for different event types
Date overrides : Block specific dates or add special availability
Minimum notice : Set how far in advance people can book
Booking window : Limit how far into the future bookings can be made
// From packages/platform/types/event-types
{
minimumBookingNotice : 1440 , // 24 hours (in minutes)
bookingWindow : {
type : "rolling" ,
value : 30 , // Book up to 30 days ahead
unit : "days"
}
}
Share your booking link
Your booking page is ready! Share it: https://cal.com/your-username
https://cal.com/your-username/30min
Direct link Share your booking URL via email, social media, or messaging
Website embed Embed Cal.com on your website with our embed components
Email signature Add your booking link to your email signature
Social profiles Add to Twitter bio, LinkedIn profile, etc.
Preview your booking page by visiting your link or clicking Preview on the event type.
Get your first booking
When someone books time with you:
You’ll receive an email with booking details
Event appears in your calendar automatically
Booker gets confirmation with meeting details
Automatic reminders are sent before the meeting
// Booking creation flow from apps/web/pages/api/book/event.ts
// 1. Validate booking against availability
// 2. Create booking in database
// 3. Add to connected calendars
// 4. Send confirmation emails
// 5. Trigger workflows (reminders, webhooks)
const regularBookingService = getRegularBookingService ();
const booking = await regularBookingService . createBooking ({
eventTypeId ,
start: selectedSlot ,
responses: bookerInfo ,
// ... more parameters
});
Bookings are managed in the Bookings tab where you can view, reschedule, or cancel meetings.
Self-hosted deployment
Deploy Cal.com
Choose your deployment method: Docker (Recommended)
Railway
Vercel
# Clone repository
git clone https://github.com/calcom/cal.com.git
cd cal.com
# Configure environment
cp .env.example .env
# Generate secrets
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 24 # CALENDSO_ENCRYPTION_KEY
# Start services
docker compose up -d
Required environment variables
# Database (included in docker-compose)
DATABASE_URL = "postgresql://unicorn_user:magical_password@database:5432/calendso"
# Application URL
NEXT_PUBLIC_WEBAPP_URL = "http://localhost:3000"
NEXTAUTH_URL = "http://localhost:3000"
# Secrets (generate with openssl)
NEXTAUTH_SECRET = "your-32-byte-secret"
CALENDSO_ENCRYPTION_KEY = "your-24-byte-encryption-key"
# Cron jobs
CRON_API_KEY = "random-string-for-cron-endpoints"
Access at: http://localhost:3000 One-click deploy with automatic database: Railway automatically:
Forks the repository
Provisions PostgreSQL database
Sets up environment variables
Deploys the application
Vercel Pro required : Free plan doesn’t support Cal.com’s serverless function requirements.
You’ll need to provide:
PostgreSQL database (Neon, Supabase, or Railway)
Environment variables (see Docker tab)
See all deployment options →
Complete initial setup
Visit your Cal.com instance
Create your admin account
Set up your profile (username, name, timezone)
// First user becomes admin automatically
// From packages/prisma/schema.prisma:77
model User {
role UserRole @ default ( USER ) // First user gets ADMIN
username String ? @ unique
email String @ unique
}
Configure integrations
Self-hosted instances require your own OAuth credentials for third-party integrations.
Go to Google Cloud Console
Create a new project
Enable Google Calendar API
Create OAuth 2.0 credentials
Add authorized redirect URIs:
https://your-domain.com/api/integrations/googlecalendar/callback
https://your-domain.com/api/auth/callback/google
Add to .env:
GOOGLE_API_CREDENTIALS = '{"web":{"client_id":"...","client_secret":"..."}}'
GOOGLE_LOGIN_ENABLED = true
Detailed Google setup guide →
Create app on Zoom Marketplace
Choose “General App” → “User-managed”
Set redirect URL: https://your-domain.com/api/integrations/zoomvideo/callback
Add scopes:
meeting:write:meeting
user:read:settings
Add to .env:
ZOOM_CLIENT_ID = "your-client-id"
ZOOM_CLIENT_SECRET = "your-client-secret"
Configure SMTP for sending booking confirmations: # SendGrid (recommended)
SENDGRID_API_KEY = "your-api-key"
SENDGRID_EMAIL = "[email protected] "
# Or use SMTP
EMAIL_SERVER_HOST = "smtp.gmail.com"
EMAIL_SERVER_PORT = 465
EMAIL_SERVER_USER = "[email protected] "
EMAIL_SERVER_PASSWORD = "your-app-password"
EMAIL_FROM = "[email protected] "
Without email configuration, booking confirmations won’t be sent. This is required for production use.
Create your first event type
Follow the same steps as Cal.com Cloud (Steps 3-6 above):
Create/customize an event type
Connect your calendar (requires OAuth setup)
Set your availability
Share your booking link
Get your first booking!
Understanding the booking flow
Here’s what happens when someone books with you:
Booker selects a time
// Available slots are calculated based on:
// - Your schedule/availability
// - Connected calendar busy times
// - Existing Cal.com bookings
// - Buffer times and booking limits
// From packages/features/bookings/lib/handleNewBooking
const availableSlots = await getAvailableSlots ({
eventTypeId ,
startTime ,
endTime ,
timeZone: booker . timeZone
});
Booker fills out form
Required information:
Name
Email
Custom fields (if configured)
Guest emails (if allowed)
// Booking fields from packages/platform/types/event-types
bookingFields : [
{ type: "name" , required: true },
{ type: "email" , required: true },
{ type: "phone" , required: false },
// Custom fields
{ type: "text" , label: "Company" , required: true }
]
Booking is created
// From apps/web/pages/api/book/event.ts
const booking = await regularBookingService . createBooking ({
eventTypeId: 1 ,
start: "2024-03-15T10:00:00Z" ,
end: "2024-03-15T10:30:00Z" ,
responses: {
name: "John Doe" ,
email: "[email protected] "
},
timeZone: "America/New_York" ,
language: "en"
});
The booking is:
Saved to database
Added to your connected calendars
Status set to ACCEPTED (or PENDING if approval required)
Notifications sent
Both you and the booker receive:
Email confirmation
Calendar invitation (.ics file)
Meeting location details
// Email templates from packages/emails
// - booking-confirmation (to booker)
// - organizer-booking-notification (to you)
// - calendar-event (ICS attachment)
Reminders (optional)
If you have workflows configured:
Email/SMS reminders before the meeting
Follow-up emails after the meeting
Custom webhooks for integrations
See Workflows documentation for setup.
Next steps
Customize your booking page Add your brand colors, logo, and custom questions
Set up team scheduling Create round-robin or collective team event types
Add workflows Automate reminders, follow-ups, and notifications
Integrate with your tools Connect CRM, payment processing, and more
Embed on your website Add Cal.com directly to your website
Use the API Build custom scheduling experiences
Common questions
How do I change my booking URL?
Go to Settings → Profile and update your username. Your booking URL is: https://cal.com/your-username
https://cal.com/your-username/event-slug
For custom domains, see self-hosting configuration .
Can I require approval for bookings?
Yes! In your event type settings:
Enable Requires confirmation
Choose whether to block the time slot while pending
Approve or reject bookings from the Bookings tab
{
requiresConfirmation : true ,
requiresConfirmationWillBlockSlot : true // Optional
}
How do I prevent back-to-back meetings?
Add buffer time in your event type settings:
Before event buffer : Time before meetings
After event buffer : Time after meetings
Example: 15 minutes before, 10 minutes after {
beforeEventBuffer : 15 , // 15 minutes before
afterEventBuffer : 10 // 10 minutes after
}
Can I limit bookings per day/week?
Yes! Set booking limits in your event type: {
bookingLimits : {
day : 3 , // Max 3 bookings per day
week : 10 , // Max 10 per week
month : 30 // Max 30 per month
}
}
Or limit total duration: {
durationLimits : {
day : 180 , // Max 3 hours of meetings per day
week : 600 // Max 10 hours per week
}
}
What if someone needs to reschedule?
Bookers can reschedule using the link in their confirmation email. You can also:
Go to Bookings tab
Click the booking
Click Reschedule
Rescheduling respects your availability and sends updated notifications. To disable rescheduling: {
disableRescheduling : {
disabled : true ,
// Or only disable within X minutes before meeting:
minutesBefore : 60
}
}
How do I handle different time zones?
Cal.com automatically handles time zones:
Your availability is set in your time zone
Bookers see slots in their time zone
Calendar events show correct times for both parties
// Time zone handling from packages/lib/date-fns
// All times stored in UTC, displayed in user's timezone
import { formatInTimeZone } from "date-fns-tz" ;
formatInTimeZone (
booking . startTime ,
userTimeZone ,
"PPpp" // Format: Jan 1, 2024, 10:00 AM
);
Troubleshooting
No available times showing
Common causes:
Availability not set : Check your schedule in Availability
Calendar conflicts : Review connected calendars for busy events
Booking notice : Reduce minimumBookingNotice in event type settings
Booking window : Extend how far ahead bookings can be made
Booking limits reached : Check if you’ve hit daily/weekly limits
Debug steps: // Check availability calculation
// From apps/web/test/lib/getSchedule
const schedule = await getSchedule ({
eventTypeId ,
startDate ,
endDate ,
timeZone: "America/New_York"
});
Calendar integration not working
Google Calendar:
Disconnect and reconnect in Apps
Ensure you granted all permissions
Check that calendars are selected in integration settings
Verify OAuth redirect URIs are correct (self-hosted)
Outlook/Office 365:
Verify calendar permissions in Azure AD
Check that API permissions include Calendars.Read and Calendars.ReadWrite
Ensure consent was granted by admin (if required)
Self-hosted only:
Verify email configuration in .env:
EMAIL_SERVER_HOST = "smtp.gmail.com"
EMAIL_SERVER_PORT = 465
EMAIL_FROM = "[email protected] "
Test SMTP connection:
# Check if SMTP server is reachable
telnet smtp.gmail.com 465
For Gmail, use an app password
Check application logs for email errors
Cal.com Cloud: Email issues should be rare. Contact support if emails aren’t being delivered.
Time zone showing incorrectly
Update your time zone in Settings → Profile
Clear browser cache and reload
Check that system time zone is correct
For event types, verify schedule time zone matches your preference
// Time zone priority:
// 1. Event type schedule timezone
// 2. User profile timezone
// 3. Browser timezone (fallback)
Getting help
Documentation Comprehensive guides and API reference
GitHub Discussions Ask questions and share with the community
Discord Chat with other Cal.com users
Enterprise support Commercial support and consulting
Now scheduling! You’re ready to start taking bookings. Share your booking link and watch your calendar fill up.