calcom/cal.diy · error · UnauthorizedException
ApiKeysService - This endpoint can only be accessed using an
Error message
ApiKeysService - This endpoint can only be accessed using an API key by providing 'Authorization: Bearer <apiKey>' header
What it means
Thrown by ApiKeysService.getRequestApiKey when request.authMethod does not equal AuthMethods.API_KEY ('api-key'). This endpoint requires API key authentication specifically, but the request was authenticated via a different method (OAuth client, access token, NextAuth session, or third-party access token). The guard has already authenticated the user, but the service rejects the request because API-key-specific operations require the API key itself for further processing (e.g. key refresh, key deletion).
Source
Thrown at apps/api/v2/src/modules/api-keys/services/api-keys.service.ts:22
import { CreateApiKeyInput } from "@/modules/api-keys/inputs/create-api-key.input";
import { RefreshApiKeyInput } from "@/modules/api-keys/inputs/refresh-api-key.input";
import { ApiAuthGuardRequest } from "@/modules/auth/strategies/api-auth/api-auth.strategy";
import { BadRequestException, Injectable, UnauthorizedException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { DateTime } from "luxon";
import { createApiKeyHandler } from "@calcom/platform-libraries";
@Injectable()
export class ApiKeysService {
constructor(
private readonly apiKeysRepository: ApiKeysRepository,
private readonly config: ConfigService
) {}
async getRequestApiKey(request: ApiAuthGuardRequest) {
if (request.authMethod !== AuthMethods.API_KEY) {
throw new UnauthorizedException(
"ApiKeysService - This endpoint can only be accessed using an API key by providing 'Authorization: Bearer <apiKey>' header"
);
}
const apiKey = request.get("Authorization")?.replace("Bearer ", "");
if (!apiKey) {
throw new UnauthorizedException("ApiKeysService - No API key provided");
}
return apiKey;
}
async createApiKey(authUserId: number, createApiKeyInput: CreateApiKeyInput) {
if (createApiKeyInput.apiKeyDaysValid && createApiKeyInput.apiKeyNeverExpires) {
throw new BadRequestException(
"ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNeverExpires. It has to be either or none of them."
);
}
const defaultApiKeyDaysValid = 30;View on GitHub (pinned to 176037d0af)
Solutions
- Switch the Authorization header to use a valid API key (Bearer cal_<key>) instead of an OAuth access token when calling API-key management endpoints.
- If you don't have an API key yet, first create one via POST /v2/api-keys using an authenticated session or access token, then use that key for subsequent API-key-specific operations.
- Check the ApiAuthGuard configuration to confirm which auth methods are accepted on the route and ensure API_KEY is among them.
Example fix
// before: using OAuth access token for key-management endpoint
const res = await fetch('/v2/api-keys/refresh', {
headers: { Authorization: `Bearer ${oauthAccessToken}` }
});
// after: use a valid API key for the Bearer header
const res = await fetch('/v2/api-keys/refresh', {
headers: { Authorization: `Bearer cal_${validApiKey}` }
}); Defensive patterns
Strategy: validation
Validate before calling
// Validate auth method before calling API-key-only endpoints
const isApiKeyAuth = (authMethod: string): boolean =>
authMethod === 'api-key';
// Ensure the Authorization header contains an API key, not an OAuth token
const ensureApiKeyAuth = (headers: Record<string, string>): void => {
const auth = headers['Authorization'] ?? headers['authorization'];
if (!auth?.startsWith('Bearer cal_')) {
throw new Error('This endpoint requires API key auth (Bearer cal_<key>). Current auth is not an API key.');
}
}; Type guard
type ApiKeyAuthHeaders = { Authorization: `Bearer cal_${string}` };
const hasApiKeyAuth = (h: Record<string, string>): h is ApiKeyAuthHeaders =>
h['Authorization']?.startsWith('Bearer cal_') ?? false; Prevention
- Document which endpoints require API-key auth vs OAuth/access-token auth in your API client SDK.
- Use separate API client instances for different auth methods to avoid accidentally sending the wrong token type.
- Before calling API-key management endpoints, verify the client was initialized with an API key, not an OAuth token.
When it happens
Trigger: Calling an API-key management endpoint (like DELETE /api-keys or POST /api-keys/refresh) while authenticated with an OAuth access token instead of an API key. The route is protected by ApiAuthGuard which sets authMethod based on which strategy succeeded, but the downstream service checks that the method is specifically API_KEY.
Common situations: A frontend app that uses OAuth login trying to manage API keys without first generating one. Swagger/OpenAPI UI using a bearer access token instead of an API key. Confusion between the OAuth access token flow and the API key flow in client code.
Related errors
- CustomThrottlerGuard - Invalid API Key
- ApiKeysService - No API key provided
- ApiKeysService - provided api key is not valid.
- Unauthorized
- ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNe
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/984a7d5adeb37346.
Report an issue: GitHub.