calcom/cal.diy · error · UnauthorizedException

checkBookingRequiresAuthentication - request must be authent

Error message

checkBookingRequiresAuthentication - request must be authenticated by passing credentials belonging to event type owner, host or team or org admin or owner.

What it means

Thrown in checkBookingRequiresAuthenticationSetting when the event type has bookingRequiresAuthentication = true and the request carries no authenticated user (authUser is null). Protected event types require credentials; an anonymous public booking is refused with HTTP 401.

Source

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

  }

  async checkEventTypeHasHosts(eventTypeId: number) {
    const eventType = await this.eventTypesRepository.getEventTypeWithHosts(eventTypeId);
    if (!eventType?.hosts?.length) {
      throw new UnprocessableEntityException(
        `Can't book this team event type because it has no hosts. Please, add at least 1 host to event type with id=${eventTypeId} belonging to team with id=${eventType?.teamId} and try again.`
      );
    }
  }

  async checkBookingRequiresAuthenticationSetting(
    eventType: EventTypeWithOwnerAndTeam,
    authUser: AuthOptionalUser,
    userIsEventTypeAdminOrOwner: boolean
  ) {
    if (!eventType.bookingRequiresAuthentication) return true;
    if (!authUser) {
      throw new UnauthorizedException(
        "checkBookingRequiresAuthentication - request must be authenticated by passing credentials belonging to event type owner, host or team or org admin or owner."
      );
    }

    if (!userIsEventTypeAdminOrOwner) {
      throw new ForbiddenException(
        "checkBookingRequiresAuthentication - user is not authorized to access this event type. User has to be either event type owner, host, team admin or owner or org admin or owner."
      );
    }
  }

  async getBookedEventType(body: CreateBookingInput) {
    if (body.eventTypeId) {
      return await this.eventTypesRepository.getEventTypeByIdWithOwnerAndTeam(body.eventTypeId);
    } else if (body.username && body.eventTypeSlug) {
      const user = await this.usersRepository.findByUsername(body.username, body.organizationSlug);
      if (!user) {
        throw new NotFoundException(`User with username ${body.username} not found`);

View on GitHub (pinned to 176037d0af)

Solutions

  1. Authenticate the request by sending a valid access token or API key for an authorized user.
  2. If public booking is intended, disable bookingRequiresAuthentication on the event type.
  3. Confirm the event type's require-auth flag before building the public flow.

Example fix

// before
await api.post('/v2/bookings', body); // no Authorization header, protected event type
// after
await api.post('/v2/bookings', body, { headers: { Authorization: `Bearer ${token}` } });
Defensive patterns

Strategy: validation

Validate before calling

// Before booking a protected event type anonymously, check its require-auth flag.
const eventType = await api.get(`/v2/event-types/${eventTypeId}`);
if (eventType.bookingRequiresAuthentication && !hasToken()) {
  throw new Error('Event type requires authentication; provide an access token or API key');
}

Type guard

function eventTypeRequiresAuth(et: { bookingRequiresAuthentication?: boolean } | null | undefined): boolean {
  return !!et?.bookingRequiresAuthentication;
}

Try / catch

try {
  await api.post('/v2/bookings', body);
} catch (err) {
  if (err.status === 401 && /must be authenticated/.test(err.message)) {
    // send Authorization header with an authorized user's token, or disable require-auth on the event type
  }
  throw err;
}

Prevention

When it happens

Trigger: POST /v2/bookings against an event type whose bookingRequiresAuthentication is enabled, without an Authorization header / API key (the public, unauthenticated booking path).

Common situations: Embed/public booking flow pointed at a protected event type; client forgot to send the access token; event type flipped to require-auth after the integration was built.

Understand the failure class

Related errors


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