What webcal:// actually is

It is not a protocol. webcal:// is a convention that means “this is a calendar feed, hand it to the calendar app rather than showing it in the browser”. The operating system swaps it for https:// and fetches the file normally. The whole trick is that clicking it opens the user's calendar app with a subscribe prompt instead of downloading a file they then have to find.

So a subscribe link is your ordinary feed URL with the scheme swapped. If your feed is at https://example.com/events/feed.ics, the subscribe link is webcal://example.com/events/feed.ics.

Subscribing versus adding

An add-to-calendar button copies one event into somebody's calendar. If the date later moves, their copy does not — they turn up on the wrong night, and they blame you rather than the button.

A subscription is a live link. Their calendar re-reads your feed periodically, so new events appear, changed times update, and cancellations disappear. For a venue with a regular programme this is the single most valuable thing you can offer a returning customer: they subscribe once and your schedule is in their pocket permanently.

Offer both. The button suits somebody interested in one show; the subscription suits the regular, and the regular is the one worth keeping.

Making it work everywhere

iOS and macOS handle webcal:// well — it opens Calendar with a subscribe prompt. Android is patchier and depends on which calendar app is installed. Desktop Outlook handles it; Outlook on the web wants the https:// address pasted into its “Subscribe from web” box instead. Google Calendar has no way to accept a webcal link directly at all: it needs the https:// URL pasted into Other calendars → From URL.

So the practical answer is to offer both forms — a webcal:// link for the phones that understand it, and the plain https:// URL shown as copyable text for everyone else, with one line saying where to paste it.

Two things that break subscriptions

Unstable UIDs. If your feed regenerates event identifiers each time it is served, every subscriber's calendar sees the entire programme as brand new on every refresh — deleting and re-adding everything, sometimes with notifications. The UID must be stable for the life of the event.

Refusing conditional requests. Calendar clients poll. Some poll often. A feed that returns the full document every time, rather than answering “nothing has changed”, costs you bandwidth and gets your feed fetched less often by clients that throttle badly-behaved sources.

How often will it update?

Not on your schedule. Google refreshes subscribed calendars on its own cadence, often measured in many hours, and there is no way to make it faster from your end. Tell people that, and publish changes with enough notice that it does not matter.