iOS Calendar subscription fails with verification failed error on Vercel hosted .ics feed

Overview

I’m hosting a Next.js / FastAPI project on Vercel that provides a dynamic iCalendar (.ics) feed for users to subscribe to. The feed works perfectly on every platform except the native iOS Calendar app, which throws a “Verification failed” error.

Environment

  • Framework: Next.js with FastAPI backend
  • Domain: www.gocutit.com
  • Endpoint: /api/sync/calendar/[user].ics
  • Vercel Plan: Hobby

What Works :white_check_mark:

  • Google Calendar subscription — works perfectly
  • Microsoft Outlook subscription — works perfectly
  • Direct browser access — returns 200 OK, downloads valid .ics file
  • The .ics file is fully RFC 5545 compliant with correct text/calendar Content-Type

What Fails :cross_mark:

  • iOS native Calendar app (Settings → Calendar → Accounts → Add Subscribed Calendar)
  • Error message:

Error: Verification failed

  • The iOS Calendar uses the dataaccessd user-agent for these requests

Troubleshooting Completed

  1. Disabled Deployment Protection via OPTIONS Allowlist for the /api/sync/calendar path
  2. Added CORS headers in vercel.json:
    • Access-Control-Allow-Origin: *
    • Access-Control-Allow-Methods: GET, OPTIONS, HEAD
  3. Tested with a static file: Placed a hardcoded test.ics file in the /public folder — same “Verification failed” error on iOS
  4. Firewall Configuration:
    • Created a custom bypass rule for path /api/sync/calendar — Rule is Active
    • Bot Protection: Disabled
    • Attack Challenge Mode: Disabled
    • Bypass rule is positioned above all other rules
  5. Verified Deployment Protection is not the issue — accessing the URL in an incognito browser successfully downloads the .ics file

Key Finding :magnifying_glass_tilted_left:

When attempting to subscribe from iOS Calendar, no requests appear in Vercel logs at all. This indicates the requests are being blocked or dropped at Vercel’s Edge layer before reaching the application.

This happens even though:

  • All protections are disabled
  • Custom bypass rules are in place
  • The endpoint is fully public and accessible from all other clients

Theory

It appears Vercel’s Edge network is specifically blocking or dropping connections from Apple’s dataaccessd user-agent, possibly due to:

  • TLS/SSL handshake handling specific to iOS
  • Some undocumented bot filtering at the Edge layer
  • The way iOS Calendar probes/validates URLs before subscribing

Request

Has anyone successfully hosted an .ics calendar subscription feed on Vercel that works with the native iOS Calendar app? Is there a known workaround or configuration required to allow the dataaccessd user-agent through Vercel’s Edge network?

Any help would be greatly appreciated!

Hi Kemal,

I’d be careful about concluding this is definitely Vercel blocking dataaccessd just from the app logs. If the request fails at TLS, redirect validation, HEAD handling, or a firewall layer before the function runs, you may also see no application log entry.

For iOS Calendar, I’d test the feed like an automated calendar client instead of only from a browser:

URL="https://www.gocutit.com/api/sync/calendar/example.ics"

curl -i -L "$URL"
curl -I -L "$URL"
curl -i -L \
  -A "dataaccessd/1.0" \
  -H "Accept: text/calendar,*/*" \
  "$URL"

I’d want all of those to return a plain 200, not a challenge page, login page, HTML page, or redirect loop. The response should look roughly like:

HTTP 200
Content-Type: text/calendar; charset=utf-8

BEGIN:VCALENDAR
VERSION:2.0
...
END:VCALENDAR

A couple of iOS-specific things I’d check:

- HEAD requests return 200, not 405/404
- the final URL after redirects is still HTTPS
- there is no auth cookie/session requirement
- no HTML is returned for unknown/expired calendar tokens
- the feed works from the apex/www version you actually paste into iOS
- the URL contains no unescaped spaces, brackets, or copied punctuation

If the dataaccessd curl test works but the phone still fails, I’d check Vercel Firewall events for the exact timestamp. A normal custom bypass rule only helps if a custom/managed rule is the thing blocking the request; if it is a TLS/DNS/validation issue, the bypass rule will not change anything.

As a stronger isolation test, I’d deploy the same static .ics file on a completely plain path like:

/calendar-test.ics

with no API route, no rewrite, no middleware, no auth, and no custom firewall rule. If iOS still fails on that plain static file while Google/Outlook work, then the next useful evidence is the exact URL form pasted into iOS, the curl -I -L output, and whether the failure happens on both Wi-Fi and mobile data.