calcom/cal.diy · error · UnauthorizedException

This event type requires authentication. Please provide vali

Error message

This event type requires authentication. Please provide valid credentials.

What it means

A 401 Unauthorized thrown by checkBookingRequiresAuthentication when the event type requires authentication, no valid rescheduleUid was supplied (or one was supplied and validated), and the getOwner method could not resolve a user from the request's Authorization header. getOwner attempts to resolve the user either from a cal_ prefixed API key or from an OAuth access token.

Source

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

      return;
    }

    if (rescheduleUid) {
      const isValidRescheduleBooking = await this.isValidRescheduleBooking(rescheduleUid, eventTypeId);
      if (isValidRescheduleBooking) {
        return;
      } else {
        throw new BadRequestException(
          "Trying to reschedule an event-type which requires authentication but provided invalid rescheduleUid."
        );
      }
    }

    const owner = await this.getOwner(req);
    const userId = owner?.id;

    if (!userId) {
      throw new UnauthorizedException(
        "This event type requires authentication. Please provide valid credentials."
      );
    }

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

View on GitHub (pinned to 176037d0af)

Solutions

  1. Include a valid Authorization: Bearer <token> header where token is either a cal_ prefixed API key or a valid OAuth access token.
  2. If using an API key, verify it starts with the correct prefix (default 'cal_') and hasn't been revoked in the user's API key settings.
  3. If using OAuth, refresh the access token using the refresh token flow and retry.
  4. Confirm the event type actually requires authentication — if bookingRequiresAuthentication was enabled by mistake, disable it in the event type settings.

Example fix

// before — missing auth header
const res = await fetch('/v2/bookings', {
  method: 'POST',
  body: JSON.stringify({ eventTypeId: 5, start: '...' })
});

// after — include valid credentials
const res = await fetch('/v2/bookings', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ eventTypeId: 5, start: '...' })
});
Defensive patterns

Strategy: validation

Validate before calling

// Validate auth credentials before calling a restricted event type
async function ensureAuthenticated(token) {
  // Test the token against any authenticated endpoint
  const res = await fetch('/v2/bookings?status=upcoming', {
    headers: { Authorization: `Bearer ${token}` }
  });
  return res.ok; // 200 means token is valid
}

if (!(await ensureAuthenticated(apiKey))) {
  throw new Error('Invalid or expired credentials — refresh your API key or OAuth token');
}

Try / catch

try {
  await api.createBooking({ eventTypeId, ... });
} catch (err) {
  if (err.statusCode === 401) {
    // Refresh OAuth token or prompt for new API key
    const newToken = await refreshOAuthToken(refreshToken);
    await api.createBooking({ eventTypeId, ... }); // retry with new token
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: POST /v2/bookings or POST /v2/bookings/recurring against an event type with bookingRequiresAuthentication=true, where: the Authorization header is missing entirely, the API key is invalid/expired/revoked, the OAuth access token is expired or invalid, or the resolved ownerId doesn't correspond to an existing user record.

Common situations: Client forgot to include the Authorization header for a restricted event type. The API key was rotated and the old one is still in use. The OAuth token expired and wasn't refreshed. The cal_ API key prefix configured in api.apiKeyPrefix doesn't match the key being sent. The user account was deleted after the API key was issued.

Understand the failure class

Related errors


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