calcom/cal.diy · error · ForbiddenException

User is not authorized to update this booking location. User

Error message

User is not authorized to update this booking location. User must be the event type owner, host, team admin or owner, or org admin or owner.

What it means

Authorization guard in updateBookingLocation. When the booking has an eventTypeId and eventType, the service loads the full event type with owner/team and runs eventTypeAccessService.userIsEventTypeAdminOrOwner. If the authenticated API user is not the event type owner, a host, a team admin/owner, or an org admin/owner, the location update is refused with HTTP 403.

Source

Thrown at apps/api/v2/src/platform/bookings/2024-08-13/services/booking-location.service.ts:61

  async updateBookingLocation(
    bookingUid: string,
    input: UpdateBookingLocationInput_2024_08_13,
    user: ApiAuthGuardUser
  ): Promise<BookingLocationResponse> {
    const existingBooking = await this.bookingsRepository.getBookingByUidWithUserAndEventDetails(bookingUid);
    if (!existingBooking) {
      throw new NotFoundException(`Booking with uid=${bookingUid} not found`);
    }

    if (existingBooking.eventTypeId && existingBooking.eventType) {
      const eventType = await this.eventTypesRepository.getEventTypeByIdWithOwnerAndTeam(
        existingBooking.eventTypeId
      );
      if (eventType) {
        const isAllowed = await this.eventTypeAccessService.userIsEventTypeAdminOrOwner(user, eventType);
        if (!isAllowed) {
          throw new ForbiddenException(
            "User is not authorized to update this booking location. User must be the event type owner, host, team admin or owner, or org admin or owner."
          );
        }
      }
    }

    const { location } = input;

    if (location) {
      if (location.type !== "integration") {
        const locationValue = this.getNonIntegrationLocationValue(location);
        if (locationValue) {
          await this.calendarSyncService.syncCalendarEvent(existingBooking.id, locationValue);
        }
      }
      return await this.updateLocation(existingBooking, location, user);
    }

View on GitHub (pinned to 176037d0af)

Solutions

  1. Use an API key / access token belonging to the event type owner, a host, or a team/org admin.
  2. Grant the authenticated user the appropriate team (admin) or organization (admin/owner) role.
  3. If the booking has no event type, this check is skipped — confirm whether the booking should have one.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the caller is authorized over the event type before PATCHing location.
// Use an API key whose user is the event type owner / team or org admin.
const me = await api.get('/v2/me');
const eventType = await api.get(`/v2/event-types/${booking.eventTypeId}`);
// verify ownership locally or rely on a dedicated permission check before calling PATCH

Try / catch

try {
  await api.patch(`/v2/bookings/${uid}/location`, payload);
} catch (err) {
  if (err.status === 403) {
    // switch to an owner/admin API key or request elevated role
  }
  throw err;
}

Prevention

When it happens

Trigger: PATCH booking location where the booking belongs to an event type, using an API key/access token whose user lacks admin/owner rights over that event type or its team/org.

Common situations: Using an API key issued for a different user than the event type owner; an org member (not admin) trying to edit a team event type's booking; booking belongs to a team the authenticated user isn't an admin of.

Related errors


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