Skip to main content
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

Fastest way to get started with zero setup

Cal.com Cloud

1

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.
2

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")
}
3

Create your first event type

Cal.com creates a default “30 Minute Meeting” for you, but let’s customize it:
  1. Go to Event Types in the sidebar
  2. Click your “30 Minute Meeting” event
  3. 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
// 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
}
  1. Click Save when done
4

Connect your calendar

Prevent double-bookings by connecting your calendar:
  1. Click Apps in the sidebar
  2. Find “Google Calendar” and click Connect
  3. Sign in and grant permissions
  4. 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"]
    }
  }
}
Important: Connected calendars are checked for conflicts. Any busy events will block those time slots from being booked.
5

Set your availability

Define when you’re available for bookings:
  1. Go to Availability in the sidebar
  2. Edit your “Working Hours” schedule
  3. 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
    }
  ]
}
  • 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"
  }
}
6

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.
7

Get your first booking

When someone books time with you:
  1. You’ll receive an email with booking details
  2. Event appears in your calendar automatically
  3. Booker gets confirmation with meeting details
  4. 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

1

Deploy Cal.com

Choose your deployment method:See all deployment options →
2

Complete initial setup

  1. Visit your Cal.com instance
  2. Create your admin account
  3. 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
}
3

Configure integrations

Self-hosted instances require your own OAuth credentials for third-party integrations.
  1. Go to Google Cloud Console
  2. Create a new project
  3. Enable Google Calendar API
  4. Create OAuth 2.0 credentials
  5. Add authorized redirect URIs:
    https://your-domain.com/api/integrations/googlecalendar/callback
    https://your-domain.com/api/auth/callback/google
    
  6. Add to .env:
    GOOGLE_API_CREDENTIALS='{"web":{"client_id":"...","client_secret":"..."}}'
    GOOGLE_LOGIN_ENABLED=true
    
Detailed Google setup guide →
  1. Create app on Zoom Marketplace
  2. Choose “General App” → “User-managed”
  3. Set redirect URL: https://your-domain.com/api/integrations/zoomvideo/callback
  4. Add scopes:
    • meeting:write:meeting
    • user:read:settings
  5. Add to .env:
    ZOOM_CLIENT_ID="your-client-id"
    ZOOM_CLIENT_SECRET="your-client-secret"
    
Configure SMTP for sending booking confirmations:
.env
# 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.
4

Create your first event type

Follow the same steps as Cal.com Cloud (Steps 3-6 above):
  1. Create/customize an event type
  2. Connect your calendar (requires OAuth setup)
  3. Set your availability
  4. Share your booking link
  5. Get your first booking!

Understanding the booking flow

Here’s what happens when someone books with you:
1

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
});
2

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 }
]
3

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)
4

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)
5

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

Go to SettingsProfile 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.
Yes! In your event type settings:
  1. Enable Requires confirmation
  2. Choose whether to block the time slot while pending
  3. Approve or reject bookings from the Bookings tab
{
  requiresConfirmation: true,
  requiresConfirmationWillBlockSlot: true  // Optional
}
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
}
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
  }
}
Bookers can reschedule using the link in their confirmation email. You can also:
  1. Go to Bookings tab
  2. Click the booking
  3. 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
  }
}
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

Common causes:
  1. Availability not set: Check your schedule in Availability
  2. Calendar conflicts: Review connected calendars for busy events
  3. Booking notice: Reduce minimumBookingNotice in event type settings
  4. Booking window: Extend how far ahead bookings can be made
  5. 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"
});
Google Calendar:
  1. Disconnect and reconnect in Apps
  2. Ensure you granted all permissions
  3. Check that calendars are selected in integration settings
  4. Verify OAuth redirect URIs are correct (self-hosted)
Outlook/Office 365:
  1. Verify calendar permissions in Azure AD
  2. Check that API permissions include Calendars.Read and Calendars.ReadWrite
  3. Ensure consent was granted by admin (if required)
Self-hosted only:
  1. Verify email configuration in .env:
    EMAIL_SERVER_HOST="smtp.gmail.com"
    EMAIL_SERVER_PORT=465
    EMAIL_FROM="[email protected]"
    
  2. Test SMTP connection:
    # Check if SMTP server is reachable
    telnet smtp.gmail.com 465
    
  3. For Gmail, use an app password
  4. Check application logs for email errors
Cal.com Cloud: Email issues should be rare. Contact support if emails aren’t being delivered.
  1. Update your time zone in SettingsProfile
  2. Clear browser cache and reload
  3. Check that system time zone is correct
  4. 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.

Build docs developers (and LLMs) love