calcom/cal.diy · error · ForbiddenException

You are not authorized to book this event type. You must be

Error message

You are not authorized to book this event type. You must be the event type owner, a host, a team admin/owner, or an organization admin/owner.

What it means

A 403 Forbidden thrown by checkBookingRequiresAuthentication when the event type requires authentication, the caller is successfully authenticated (a valid user was resolved), but the user lacks authorization for this specific event type. Authorization is granted if the user is the event type owner, a listed host, a team admin/owner of the event type's team, or an organization admin/owner of the parent org.

Source

Thrown at apps/api/v2/src/platform/bookings/2024-04-15/controllers/bookings.controller.ts:492

    const isEventTypeOwner = eventType.userId === userId;
    const isHost = eventType.hosts.some((host) => host.userId === userId);
    const isTeamAdminOrOwner = eventType.team?.members.some((member) => member.userId === userId) ?? false;

    let isOrgAdminOrOwner = false;
    if (eventType.team?.parentId) {
      const orgTeam = await this.teamRepository.getTeamByIdIfUserIsAdmin({
        userId,
        teamId: eventType.team.parentId,
      });
      isOrgAdminOrOwner = !!orgTeam;
    } else if (eventType.team?.isOrganization) {
      isOrgAdminOrOwner = isTeamAdminOrOwner;
    }

    const isAuthorized = isEventTypeOwner || isHost || isTeamAdminOrOwner || isOrgAdminOrOwner;

    if (!isAuthorized) {
      throw new ForbiddenException(
        "You are not authorized to book this event type. You must be the event type owner, a host, a team admin/owner, or an organization admin/owner."
      );
    }
  }

  private async getOAuthClientsParams(clientId: string, isEmbed = false): Promise<OAuthRequestParams> {
    const res = { ...DEFAULT_PLATFORM_PARAMS };

    if (isEmbed) {
      // embed should ignore oauth client settings and enable emails by default
      return { ...res, arePlatformEmailsEnabled: true, areCalendarEventsEnabled: true };
    }

    try {
      const client = await this.oAuthClientRepository.getOAuthClient(clientId);
      // fetch oAuthClient from db and use data stored in db to set these values
      if (client) {
        res.platformClientId = clientId;

View on GitHub (pinned to 176037d0af)

Solutions

  1. Verify the authenticated user has one of: event type ownership, host membership, team admin/owner role, or org admin/owner role for this event type.
  2. If the user should be a host, add them to the event type's hosts list in the Cal.com dashboard or via the event types API.
  3. If the user should have team-level access, promote them to team admin or owner in the team settings.
  4. Confirm the correct eventTypeId is being requested — a typo can point to an event type the user has no relation to.

Example fix

// before — regular team member attempts to book restricted event type
POST /v2/bookings { eventTypeId: 42 }
// Authorization: Bearer <regular-member-token>  -> 403

// after — either promote the user to team admin or use an authorized user's token
POST /v2/bookings { eventTypeId: 42 }
// Authorization: Bearer <team-admin-token>  -> 200
Defensive patterns

Strategy: validation

Validate before calling

// Check if the user is authorized for the event type before booking
async function canUserBookEventType(userToken, eventTypeId) {
  const res = await fetch(`/v2/event-types/${eventTypeId}`, {
    headers: { Authorization: `Bearer ${userToken}` }
  });
  if (!res.ok) return false;
  const { data } = await res.json();
  // Verify the user is owner, host, or team/org admin
  return data.userId === currentUserId || data.hosts?.some(h => h.userId === currentUserId);
}

if (!(await canUserBookEventType(token, eventTypeId))) {
  throw new Error('User not authorized for this event type — request access from the team admin');
}

Try / catch

try {
  await api.createBooking({ eventTypeId, ... });
} catch (err) {
  if (err.statusCode === 403) {
    // Surface to the user that they need elevated permissions
    console.error('Access denied. Request team admin or owner role for event type', eventTypeId);
  }
  throw err;
}

Prevention

When it happens

Trigger: POST /v2/bookings or POST /v2/bookings/recurring with valid credentials against a restricted event type, where the authenticated user is: not the owner (eventType.userId mismatch), not in the eventType.hosts array, not a team member with admin/owner role, and not an org admin/owner of the parent organization.

Common situations: A user was added as a regular team member (not admin) and tries to book a restricted team event type. The event type was moved to a different team and the user's membership is stale. The user belongs to a child team but the org-level check requires parent org admin role. A host was removed from the event type but still has an API key.

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/3ce5846d953fb551. Report an issue: GitHub.