Skip to content

Subscribe to the Calendar Feed

The personal calendar subscription feed is a token-protected feed.ics endpoint that lets you see every upcoming bill due date in your existing calendar app — Apple Calendar, Google Calendar / Android, Outlook, and any generic ICS client.

This page explains how the feed works, how to create a token, how to regenerate or revoke one, and how to subscribe in each major calendar app.

Why a separate feed?

Manual entry of recurring bills is error-prone and easy to forget. Subscribing once in your calendar app keeps every device, every reminder, and every share (family calendar, work calendar) in sync automatically. The feed updates whenever you create, edit, or delete a bill.

How does the feed work?

The feed is a stable URL of the form:

https://bills.example.com/api/calendar/feed.ics?token=<your-token>

The token is a per-user secret stored hashed in the calendar_tokens table. The feed endpoint:

  • Does not require session cookies (bearer-style URL)
  • Uses stable per-bill-cycle event UIDs, so subscribed events are never duplicated when the feed updates
  • Emits all-day DATE events (not DATE-TIME) with CRLF line endings, no BOM, and no VTIMEZONE block
  • Returns ics content directly without server-side caching

Migration v0.99 (calendar tokens) is idempotent — it can be re-run on a fresh database without error.

How do I create a feed token?

From Settings → Calendar Feed:

  1. Click Create feed URL.
  2. Optionally give the token a label (e.g. "iPhone", "Work Calendar").
  3. Copy the URL. BillTracker never shows the URL again — if you lose it, you must regenerate.

How do I regenerate or revoke a feed token?

The card offers three actions on the active token:

Action Effect
Copy Re-copy the current feed URL to the clipboard
Regenerate Revokes the existing token and issues a new URL. Any calendar app using the old URL stops receiving updates.
Revoke Deactivates the current token. Use this when decommissioning a device or sharing access.

The Preview button shows the next 10 events that will be emitted by the feed (dates, summaries, and UIDs) so you can verify the subscription before subscribing.

How do I subscribe in my calendar app?

Platform-specific instructions

The card in Settings has a short guide for each platform. The general pattern is "Add Calendar → Subscribe from URL" or "Add Calendar → From Web".

Apple Calendar (macOS / iOS)

  1. File → New Calendar Subscription (macOS) or Settings → Mail, Contacts, Calendars → Add Account → Other → Add Subscribed Calendar (iOS).
  2. Paste the feed URL.
  3. Set auto-refresh to Every day or Every hour.
  4. Optionally choose an alert offset (e.g. 1 day before).

Google Calendar (Web / Android)

  1. Other calendars → + → From URL.
  2. Paste the feed URL.
  3. Google fetches the feed every few hours; on Android the calendar syncs through the Google account.

Outlook (Web / Desktop)

  1. Add calendar → Subscribe from web.
  2. Paste the feed URL.
  3. Give the calendar a name and a colour.

Generic ICS Client

Any client that supports text/calendar MIME and HTTP polling can subscribe. The feed is standards-compliant and parses with most implementations.

How private is the feed URL?

The feed URL is a bearer credential. Anyone with the URL can read your upcoming bill list. Treat the URL like a password:

  • Do not paste it into public channels
  • Use Regenerate if you suspect it has been seen by the wrong person
  • The token is hashed in the database; BillTracker operators with filesystem access cannot read the raw URL from the SQLite file

What do the events look like?

Each event is an all-day entry:

BEGIN:VEVENT
UID:billcycle-1234-2026-05@bill-tracker
SUMMARY:AT&T
DTSTART;VALUE=DATE:20260529
DTEND;VALUE=DATE:20260530
DESCRIPTION:Amount $332.97
END:VEVENT

Stable UIDs mean a calendar app that supports the X-PUBLISHED-TTL / refresh cycle will update the same event rather than duplicating it.

Which API endpoints back the feed?

Method Path Purpose
GET /api/calendar/feed Fetch the current feed token and URL
POST /api/calendar/feed Create the feed token if one does not exist
POST /api/calendar/feed/regenerate Revoke the current token and issue a new URL
DELETE /api/calendar/feed Revoke the active feed URL
GET /api/calendar/feed/preview Next 10 events shown before subscribing
GET /api/calendar/feed.ics?token=<token> Public ICS feed (no session)

See also

Next steps