ICS feed validation incorrectly rejects valid iCalendar feeds when the URL does not end with .ics.
The current validation logic appears to enforce a .ics suffix:
@Matches(/\.ics$/)
This causes standards-compliant ICS/CalDAV feeds to be rejected if they are exposed through dynamic URLs or query-parameter-based export endpoints.
For example, the following URL returns a valid iCalendar feed:
https://caldav.soverin.net/calendars/MyCalendar-REDACTED?export
The endpoint responds successfully with:
Content-Type: text/calendarBEGIN:VCALENDAR contentHowever, it is rejected solely because the URL does not end with .ics.
The iCalendar and CalDAV specifications do not require ICS feed URLs to end with .ics. What matters is the response content and MIME type, not the URL structure.
Relevant specs:
Open the Cal.com ICS feed integration flow/API endpoint
Enter a valid ICS feed URL that does not end with .ics
Example:
https://caldav.soverin.net/calendars/MyCalendar-REDACTED?export
Attempt to save/create the ICS feed
Additional context:
text/calendarI consider this a bug because the implementation validates the URL shape instead of validating the actual HTTP response and calendar content.
.icsAny valid iCalendar feed URL should be accepted regardless of URL suffix
Validation should be based on:
Content-Type: text/calendarBEGIN:VCALENDARValidation logic:
@Matches(/\.ics$/)
Example valid feed:
https://caldav.soverin.net/calendars/MyCalendar-REDACTED?export
Response headers:
Content-Type: text/calendar
Node.js version:
N/A (using cal.com hosted version)
Browser:
Firefox, and also tried through the cal.com API
Tested by:
Content-Type is text/calendar.ics suffix validationThe cal.com UI wasn't very helpful as it only showed a very basic message:
I also ran the curl command which showed explicitly that the missing .ics suffix was the culprit:
% curl --request POST \
--url https://api.cal.com/v2/calendars/ics-feed/save \
--header 'Authorization: REDACTED' \
--header 'Content-Type: application/json' \
--data '
{
"urls": [
"https://REDACTED:[email protected]/calendars/MyCalendar-REDACTED?export"
],
"readOnly": true
}
'
{"status":"error","timestamp":"2026-05-07T20:01:29.624Z","path":"/v2/calendars/ics-feed/save","error":{"code":"BadRequestException","message":"Bad Request Exception","details":{"errors":[{"target":{"readOnly":true,"urls":["https://REDACTED:[email protected]/calendars/MyCalendar-REDACTED?export"]},"value":["REDACTED:[email protected]/calendars/MyCalendar-REDACTED?export"],"property":"urls","children":[],"constraints":{"IsICSUrlConstraint":"The URL must be a valid ICS URL (ending with .ics) pointing to a public host"}}]}}}%