Why Uniform Changelogs
How we normalize vendor RSS, Atom, HTML, and GitHub releases
The problem
Every vendor publishes changelogs differently. Some use RSS, some use Atom, some publish HTML without a feed, and some use GitHub releases. If you want to track updates from 50 vendors, you need 50 custom parsers.
How we normalize
Watch Changelog reads all four formats and normalizes them into one JSON shape:
- RSS and Atom: We parse the feed and extract title, date, summary, and URL.
- HTML: We load the changelog page and extract structured data using custom adapters for each vendor.
- GitHub releases: We use the GitHub API to fetch release metadata.
What you get
Every changelog entry, regardless of source format, becomes a ChangeEvent with the same fields: source, vendor, id, published_at, title, url, summary, is_important, tags, and optional typed fields (change_kind, effective_at, sunset_at).
This means your code does not change when Stripe switches from HTML to RSS, or when a vendor adds a new field to their feed.
Vendor timestamp, not scrape time
We track two clocks: the vendor's published date (published_at) and when we fetched the row (scraped_at). We never use scrape time as the vendor timestamp. If a changelog page only has a date (no time), we use the start of that day in GMT (YYYY-MM-DDT00:00:00.000Z). If there is no parseable date, we skip the entry.
Fetch timing
We fetch changelogs about once every 24 hours. If a vendor publishes an update at 9:00 AM, we fetch it during the next daily run, which could be up to 24 hours later. The entry's published_at will be 9:00 AM (the vendor's timestamp), but it appears in your API results after we fetch it. We do not promise minute-level or hourly latency. No hourly-cadence plan is currently published.