Governance deadlines are the one crypto event you cannot catch up on afterwards — a vote you missed is simply gone. Forty lines and a cron entry.
The documented ?active=true parameter returns nothing (see below), so the window is computed from starts_at and ends_at. That turns out to be the more useful shape anyway: "open right now" is a weaker question than "open right now and closing inside three days".
Proposals open and close continuously, so hourly is enough and daily misses short votes. Keep the hash of everything you have already alerted on, or you will re-send the same proposal every hour for three days.
Produced by running the code above against the live API, not written by hand.
Actual output, 15 Sep 2026. Those three Arbitrum rows are not a bug and not duplicates — they are three separate Snapshot proposals whose titles share a 52-character prefix. Widen the column or print the url; identify on hash, never on the title.
The same shape, pointed somewhere else. Every figure below came back from the live API.
Watch one DAO instead of all of them
tags=arbitrum pulls the whole Ethereum-adjacent ecosystem. sources=arbitrum_dao returns the 171 proposals that are actually Arbitrum's.
Alert on opening, not closing
Flip the window to starts_at within the last hour and you get a feed of proposals as they go live — better for a delegate who wants to read early than for a voter who wants a deadline.
Post it somewhere
The alert list is plain text, so any webhook takes it. A Discord channel is the usual destination, and that is its own recipe.
?active=true returns nothing
The parameter is documented on /items/dao/ and it does not work: active=true returns 0 results, active=false returns all 6,603. Filter on starts_at and ends_at client-side instead, which is what the code above does. Reported to the API team.
period does not apply to governance
Proposals carry starts_at and ends_at rather than published_at, so a period filter passes through without narrowing anything. Window governance on its own dates.
Do not truncate titles to dedupe
Three separate Arbitrum proposals shared a 52-character prefix and looked like one row repeated. Distinct items have distinct hash and url values; use those to identify, and the title only to display.
Automate a weekly ecosystem digest
~25 min · Python, stdlib only
Crypto data for a Discord bot
~20 min · Python, discord.py