Fixed some issues with the subscribe modal on mobile (thanks, Westley!)
Fixed benign bug with /v1/attachments when passing malformed Android data
Removed an N+1 from /v1/emails
Tweaked the docs layout a bit
Added a stricter regex for color fields in the API
Moved around the whitelabeling toggle in Settings
Improved the OpenAPI spec to preserve nullable types in the API
Fixed some z-index issues in the core author-facing app
Fixed bug where we weren't pre-emptively gating tags behind the paywall in the frontend for paid subscriptions
Improved the styling of the Data settings page
Fixed issue for authors commenting when they had multiple permissions
Improved behavior of scrolling on drawers
Fixed a bug where competing bulk actions could get stuck
Added an example of using radio buttons in subscription forms
Got rid of /settings/domains and moved the inputs into the hosting and sending pages
Added Link headers to paginated API responses
Nick improved copy for the 100th subscriber milestone email
Vended and rewrote littlefoot, our inline footnote provider
Added support for Bookshop embeds
Added support for Nepali as a supported locale for subscriber-facing content like archives
Renamed the design pages — "Archive design" is now "Web" and "Email design" is now "Email" — and moved them into their own /settings/design folder
Added rate limiting to magic links for privacy
Added the ability to set up custom click tracking domains via self-service
Fixed an edge case with slug uniqueness for emails coming from RSS-to-email
Cached DNS lookups for a minute to speed up the domains settings page
Formally removed the should_track_replies option — reply tracking is now always-on
Fixed a bug where you could turn off permissions on your own legacy API key
Added better billing flows for teams
Added inbound reply routing so username@buttondown.com gets routed to the account owner
Fixed a broken button in automation detail drawers
Improved documentation around buttondown-editor-mode
Made reply tracking always-on for all newsletters — replies are now automatically tracked through Buttondown, so there's no toggle to worry about. If you have a custom reply-to address, that still takes priority.
Added support for one-time PWYW payments via the embedded checkout flow for paid subscriptions
Added create_gift_subscriber automation action
Resurfaced subscriber referrals setting in /settings/general for analytics
Tweaked magic link emails to not reference "managing subscriptions" if they were sent via paywall
Added the Firewall to magic links
Updated the cookie policy doc with specific timing information for privacy
Improved image resizing in Fancy Mode
Add support for aggregating emails based on open rate
Migrated core app to Vite 8
Updated the stack with various changes
Fixed a bug with the CLI incorrectly duplicating images
Fixed a bug with the announcement_bar_visibility schema type
Added support for saving subscriber filters as custom segments
Added stronger idempotence when creating new Stripe prices
Fixed a bug with newly created exports not being found
Added a firewall facet for comment text that looks spammy due to URLs
Fixed a bug with the rename metadata modal action
Improved the UX of stale filters when changing a trigger within automations
Turned on CSS inlining for everyone
Fixed a bug where we were flagging base64 content was potentially having prohibited keywords
Added a link from the survey drawer to any automations which reference it
Added support for detecting Netlify-proxied requests in the API
Fixed bug where draft deliveries were being counted in analytics
Unshipped sharing_networks and started deriving it from an author's social links
Reorganized the email detail drawer
Moved advanced paid subscriptions settings into their own drawer
Fixed bug where embeds in Fancy Mode were autoexpanding on list items
Added a highlight affordance for various content addons in archives
Added a small FAQ about "guest customers" in Stripe
Fixed some edge case jank with automations
Improved the design of /settings/data
Added a bespoke timepicker
Added an annex to the Data Processing Agreement
Added PATCH /v1/images to change metadata after uploading
Fixed bug where the save tray wasn't handling archive navigation links correctly
Reorganized the blog categories a tiny bit
Combined the dark mode + light mode color variants for settings
Added the ability to choose blockquote styles
added an A/B test for /pricing CTA
Redesigned /stack
Filtered out inoperational domains from subscriber imports
Fixed issue with dropping an image into the caption of another image
Refreshed and clarified all legal docs — DPA, privacy policy, sub-processor list, and cookie policy
Fixed the save button getting stuck when switching to or from Naked Mode
Fixed a few edge cases with Stripe price creation for paid subscriptions
Fixed a bug where absent values in PATCH requests were being treated as nulls in the API
Fixed issue where updates to subscribers were hanging on the clientside after navigating from search
Updated the legal docs
Fixed a bug with images refusing to scale down on Outlook Desktop
Added metadata to /v1/images
Fixed a bug with improper validation on transactional email templates
Added a constraint to PATCH /v1/emails that forbids empty bodies for non-draft emails
Fixed a bug where our draft sending was very naively detecting paywalls
Fixed bug when editing automations with the create_export action
Reordered comments to colocate replies
Gated setting custom domains via the API behind the paywall
Expanded the firewall to better detect Shannon entropy
Added background colors to archival theme customization
Improved the todo for migrating older API keys
Showed legacy API keys in /keys alongside the new adhoc keys
Fixed bug with firewall aggression being high for embedded iframes
Started requiring magic link access before viewing subscriber-specific archives
Fixed bug where portal dashboard was not respecting custom domains for newsletters
Improved the color picker even more
Improved blockquote readability in dark mode
Formally archived the GitHub roadmap
Started preserving referrer URL even with CAPTCHA resubmission
Fixed a bunch of meta descriptions
Improved Tidal integration
Fixed bug with premium unsubscriptions being overridden by webhook race conditions
Fixed bug with survey detail page not showing which emails it was sent in
Fixed bug where replies to drafts were not being tracked
Improved error message for invalid slugs
Fixed odd bug with malformed subscriber import metadata
Fixed imprecise time estimates when scheduling an email
Redesigned the automations flow to be more conducive for multi-step automations
Added an automation action for updating email visibility
Fixed some bad marketing site styling on mobile
Added a three day grace period when deleting newsletters
Added the ability to right-click on a row to pull up its options in /emails et al
Fixed a bug which allowed creating "sent" emails without a secondary_id
Fixed a bug where some subscribers were being omitted from the comments drilldown modal in analytics
Improved the inputs for archive footer/header
Improved the design of social inputs
Fixed the archives' hamburger button height
Improved the performance of batch checking many links
Shipped a new API version with safer defaults for sending emails
Fixed benign bug when browsing archives via the TikTok browser
Fixed bug where failed Bluesky crossposts were stuck as pending
Added frontend support for passkeys
Fixed bug with rendering previews for snippets in web
Added HTML support for some transactional emails
Added passkey support for two-factor authentication
Fixed bug with Newsletter.social that had “handle” instead of “url” somehow
Cleaned up the “about to send / sending” dialog
Fixed bug where we allowed you to remove the publish date from a scheduled email
Rebuilt the color picker
Fixed bug where /paid-subscriptions would show odd data for authors with >100 prices
Fixed lingering pay-per-email setup bug
Fixed bug where the auto-generated share image would sometimes get "stuck" on the original creation date
Improved styling of template variables in Fancy mode on mobile
Fixed bug where the CLI would no-op broken images whilst downloading
Changed email API defaults so POST to /v1/emails creates drafts instead of sending immediately
Added descriptions and examples to list filter fields in the OpenAPI spec
Added the ability to choose an API version when creating a new key
Fixed a bug where resubscribed subscribers still had an undeliverability_date
Fixed a bug where snippet previews were not showing up in emails
Started flagging when connected Stripe accounts had disabled payments
Fixed some jank in the 404 template for the classic theme
Fixed a bug where some replies to support conversations were showing up in the inbox as if they were from support
Improved sponsorship management flow a bit
Improved keyboard accessibility of the newsletter switcher
Fixed bug with route-based filtering in the API requests page
Added recovery codes as a backup for two-factor authentication
Publicly launched the new version of the API with TypeID
Fixed bug with very long archive import filenames
Fixed bug with parsing CSVs that had entirely blank columns
Fixed bug with JSON validation for Newsletter.socials
Improved the /keys drawer UI
Added the import date to the drawer for completed subscriber imports
Started sending attempted events when we send emails ad-hoc (such as bulk actions)
Fixed bug with unicode characters within custom buttons being rendered oddly
Added support for recovery codes for 2FA
Added configure button to /settings/domains even if the domain is already set up correctly
Inlined the specific Archives settings so they're colocated with their toggle
Fixed bug where font changes weren't previewing correctly
Fixed bug where paywalls weren't previewing correctly for premium subscribers on web
Improved display of classic-theme emails in the editor whilst in dark mode
Replaced the inline MFA field with a distinct second screen
Fixed bug with rendering some Twitter URLs
Added a badge for custom buttons without custom URLs (thanks, Jacob!)
Added filtering in /emails by opens/clicks/deliveries
Fixed bug where fingerprinting in iFrames wasn't carrying over
Removed avatars from the RSS feed for this very page (thanks, Mark!)
Fixed bug where a few lifecycle emails didn't have an unsubscribe link
Stopped marking a domain as having an RSS feed if that domain just 307'd to Buttondown
Moved API version migration to a per-key level
Added tolerance to 2FA so you can take your time (h/t @mary)
Fixed bug with previewing older versions of CSS (h/t @mary)
Improved automation validation in external APIs
Fixed bug where we allowed you to create PWYW prices with identical minimum and maximum prices in paid subscriptions
Tweaked API rate limiting to count failures as well as successful requests
Added a slew of details to our OpenAPI spec
Tweaked magic link to reject email addresses without a matching subscriber
Improved the archive import success drawer
Reintroduced email.url template variable
Fixed bug in Beehiiv importer to handle smaller imports
Added stricter checking of imported subscribers against our existing ESP list
Fixed two edge case bugs with our CLI

Made newsletter metadata available in email templates via {{ newsletter.metadata }}
Improved visibility into why subscriber imports' rows are filtered out
Fixed bug where we allowed invalid automations to be created via API
Fixed bug where /home failed to load when a newsletter has pending sponsorships
Fixed bug introduced by Twitter in their batch tweet API
Added the ability to disconnect from SSO/password
Cut a new version of the API which allows parameterizing timing per-action
Added the ability to create new draft emails from old RSS items
Fixed bug with filtering emails in the API by -status
Fixed a smattering of broken images in docs
Added an activity item in /home for when your billing plan/status changes
Fixed bug where we asked you to supply a cadence for per-email pricing in paid subscriptions
Fixed benign NUL byte bug when storing unknown archive imports
When you downgrade from a paid plan to free, custom domains are now disabled (consistent with other features).
Fixed Apple Music embeds not working in the email preview—Apple now requires the name slug in embed URLs
Fixed 500 errors when previewing transactional emails (e.g. subscription confirmation) with invalid template syntax like empty variable tags in the Fancy Mode editor
Pushed back the paywall for RSS-to-email to activation, not creation
Added importing of arbitrary HTML blobs
Bumped up rate limit for Zapier users in good standing
Fixed bug with programmatically setting related emails for an email by slug via the API
Improved login CTA for paywalled content
Redesigned the search modal for the docs
Added an integration for Tidal
Added support for Apple Music embeds in a different format
Fixed clientside permissions issues for users with read-but-not-write subscribers permissions
Improved RSS-to-email creation flow
Fixed email-only paste handling in textareas
Cleaned up the automations UI
Added Firewall rule for penalizing email addresses which failed to subscribe to other newsletters
Improved UX for subscribing whilst authenticated as a subscriber to another newsletter
Improved various parts of the automations UI
Improved the copy of premium emails sent to paid subscribers
Fixed the janky styling of the forgotten password page
Fixed (hopefully!) another infinite-reload bug
Fixed a bug when navigating across integrations drawers
Improved performance of Fancy Mode editor
Added Firewall rules around common spammy patterns
Redesigned the security/account pages
Added the ability to filter comments by email or date
Finished cleaning up the docs
Improved the Archives marketing page
Fixed a remaining subset of CORS/preload issues
Retooled KYC messaging
Moved paid subscriptions to the sidebar if enabled
Added "other" fallback archive import for unbuilt importers
Fixed "alternatives" cards looking wonky
Slightly restyled comments
Fixed trivial timezone bug with Stripe subscriptions
Added custom click tracking domains so links route through your own sending domain

Added a big batch of new newsletter settings fields to the API
Started rolling out Cloudflare Turnstile on custom domains to reduce bot signups
Added embedded checkout to upgrade flows for paid subscriptions
Renamed "Archive design" to "Archives" for clarity
Exposed a bunch more newsletter settings to the public API
Added a bunch of FAQs to feature pages
Fixed one last R2 issue with the portal list page
Fixed a mismatch in newer Stripe API version cadences for paid subscriptions
Rebuilt the snippet editor to allow naked mode and be full page
Standardized some buttons in the manage subscription view and added a backlink
Added a new dynamic drilldown component for nested data
Added initial backend support for further webwall customization
Revamped reply tracking to be automatic and always-on
Emails that are scheduled rather than immediately sent now get hit with validators at schedule time rather than when they get published
Fixed bug where we were failing clientside to show a new paid subscription price after creating it
Added a better description for when you're missing your DMARC policy
Fixed a few benign API/validation bugs
Tweaked paid subscriptions behavior to just always mark the most recently created price as the default
Removed the duplicate email OutgoingEmailValidator and now just prompt for confirmation before sending
Improved OpenAPI schema for RSS feed endpoints
Bumped up css-inline which should fix some edge cases where inline styles were getting overridden

Made the full HTML email template editor self-serve for Professional plan users
Fixed bug with updating email addresses in the manage subscription page
Fixed bug with going from PWYW to non-PWYW if you already had a dormant PWYW price
Started rejecting email bodies that look like they have frontmatter since it's probably a mistake
Fixed pagination bug with deliveries in the email analytics drilldown
Fixed bug with the CLI modifying irrelevant files
Fixed benign Unicode surrogate bug
Fixed benign bug in the automation analytics endpoint
Started vouching for email addresses that have old ESP suppressions if they complete double opt-in
Added subject line editing to Naked Mode
Added the ability to expand the subscriber import drawer to full width
Improved the timezone/locale input
Desensitized the RSS feed alerts
Fixed broken link in docs
Improved copy for empty state on /subscribers
Added auto-linking for type IDs in /requests
Added a generator meta tag for Simple Analytics
Added a confirmation step for deleting your account
Fixed bug with migrating your API version if you had many keys
Fixed bug with unsubscription events summary being different than the drilldown
Improved retry logic on emails which we had to backoff due to rate limiting
Simplified cancellation by merging pause and cancel into one action
Cleaned up the "getting started" docs
Debounced the number of times we update RSS subscriber count for a newsletter
GA'd custom email templates via the whitelabeling entitlement
Fixed bug with TypeID on embedded forms
Started warning people about API keys in frontend places
Allowed X-Buttondown-Live-Dangerously to bypass CORS in /v1/images
Cleaned up more blog post descriptions
Cleaned up more docs
Fixed 500 when passing invalid parameters to send-draft endpoint
Removed the ability to unsubscribe directly from the "portal dashboard"
Fixed bug with the CSS editor's current-line highlighting
Fixed bug where we were incorrectly showing blockquotes as dark mode in the preview
Fixed bug where we were not sending out invitations to older accounts that already existed
Fixed bug with inconsistent image sync in the CLI
Fixed bug where naked mode welcome emails still showed frontmatter
Fixed bug where we failed to sync authors in RSS feed with very long names
Started flagging default/placeholder alt text in the email validator
Added Obsidian to the /stack
Started setting unsubscription_date for imported unsubscribers
Fixed bug where we threw a 500 if you tried to aggregate by click/open date
Started surfacing support threads in the /inbox
Improved the subscription experience on mobile by turning the CTA into a modal
Fixed bug with LinkedIn social icons not being set
Moved social links from Archives to general settings because they're used for emails, too
Fixed the Integrations marketing page looking janky
Fixed bug where we were failing to parse reply-to-replies in Postmark
Improved the /changelog layout
Fixed a bug where we weren't showing KYC questionnaire to users who hadn't finished/skipped onboarding
Removed paused subscriptions and merged them into cancellations
Fixed bug where whitelabeling was not toggleable from the general settings
Fixed bug where Markdown versions of docs weren't resolving correctly
Added Swedish as a supported locale for subscriber-facing content
Fixed bug with double-conversion from cents-dollars for PWYW prices in USD
Added the ability to filter and send to subscribers based on open/click rate
Improved process of keeping author's sending email in sync when they add a new sending domain
Started truncating API requests to the past month rather than the past year
Started prompting folks who were referred by a friend/colleague to select the username for referral's purposes
Fixed display issue when we show null percentages

Added Swedish localization for subscriber-facing pages
Added a theme option to tweak size of blockquotes
Allowed passing in subscriber_id alongside POST /v1/comments
Fixed a bug where we missed a folder when uploading assets to R2
Exposed the per-subscriber open and click rates via the API
★ Started automatically parsing all Postmark and Mailgun emails for custom domains
Added X-Buttondown-Live-Dangerously to bypass SVG prohibitions in /v1/images
Added the ability to make certain images non-zoomable
Fixed bug with input validation on analytics endpoints
Started checking ESP suppressions in firewall
Fixed QR code visibility in dark mode
Added support for PWYW subscriptions with specific cadences
Added referral source autocompletion during onboarding
Fixed some jankiness with the test mode banner on emails
Removed the ability to unsubscribe unactivated subscribers
Polished and published /settings/data
Added syntax highlighting to code snippets in comments
Documented the X-Buttondown-Bypass-Firewall header
Cleaned up a few jank areas in Lovelace
Fix a broken doc and update a bunch more besides
Fix some broken images
Renamed css_tokens to theme_configuration
Fixed bug with double h1 on archive pages
★ Migrated our static assets to be hosted on Cloudflare R2, reducing failures during deploys
Added basic metadata extraction + application for folks migrating from Substack/Beehiiv
Fixed a race condition with clientside currency conversion when setting up paid subscriptions
Fixed bug where we incorrectly failed to parse valid URLs with unicode in them when rendering Markdown
Fixed bug where we were proxying all SimpleAnalytics data onto our account
Added some more onboarding todos
Fixed bug where we weren't showing images in tracked replies
Fixed bug where export → Markdown wasn't working for individual emails
Ported the new date widget to /analytics
Standardized and cleaned up our context menu component
Improved reply HTML sanitization even more
Started prompting disabled users to provide socials
Started rejecting SVGs for newsletter icons b/c they break in emails
Started stripping as_embed param from magic link redirects so people don't get stuck in a tiny box
Migrated /v1/bulk_actions to use TypeID
Fixed bug where we asked people to supply KYC info even if they already had
Fixed some more edge cases with HTML in the /inbox
Cleaned up the footer for emails we send to premium subscribers
Added a cross-platform date picker
Fixed tiny bug where the link checker was flagging template tags like [Click here]({{ manage_subscription_url }})
Fixed bug where we weren't sanitizing HTML from emails in the inbox/conversation views
Improved editor toolbar on mobile
Fixed bug where sending an email via bulk action right after sending a draft could send the draft variant of the email
Changed the date-based cutoff for tracking domains to a flag-based one
Added public descriptions for tags, shown in the subscriber portal
Cleaned up a whole bunch of Archives docs
Migrated even more forms to use Formisch and a slightly revised design system
Added a few new lifecycle emails and removed stale ones that were dead code
Fixed benign bug in /v1/emails
Started deleting stale ESPSuppressions
Fixed bug where announcement bar was showing even in embedded subscribe forms
Fixed (hopefully) some transient deadlock/DB race conditions that were slowing down our asynchronous action runner
Fixed bug where we were asking disabled newsletters to submit KYC information even if they already had
Improved the storybook: better routing, a keyboard shortcut menu, and a request pane
Start exposing reasons why a subscriber is blocked by the firewall to authors
Start to require/add a custom CNAME for tracking domains for larger senders to derisk our own deliverability
Cleaned up a whole bunch of docs
We now have an admin action for ESPSuppression to allow removing/purging that suppression from the backing ESP
Fixed some broken links in our KYC disablement emails
Completely migrated off of DNSimple in favor of Cloudflare
Deleted a lot of old code (removed old dependencies, unused ESPs, etc.)
Migrated most forms to use Formisch and a slightly revised design system
Published an OpenAPI spec for the full archive template context
Migrated most forms to use Formisch and a slightly revised design system
Deleted a lot of old code (removed old dependencies, unused ESPs, etc.)
Completely migrated off of DNSimple in favor of Cloudflare
Fixed some broken links in our KYC disablement emails
We now have an admin action for ESPSuppression to allow removing/purging that suppression from the backing ESP
Cleaned up a whole bunch of docs
Start to require/add a custom CNAME for tracking domains for larger senders to derisk our own deliverability
Start exposing reasons why a subscriber is blocked by the firewall to authors
Made surveys work on web archive pages, not just in email
Removed redis requirement from demo to cut down on 500s
Fix bug where tags could not be programmatically set for certain weird billing cases
Fix bug where some automation actions had no label set for them
Fix bug where invoices were showing in $$$ regardless of currency
Fix bug where we allowed people to bypass the CSS billing constraints via API
Started running the email analytics cacher more often now that it's cheap
We now only see newsletters in the KYC queue if they've filled out the /home questionnaire after being disabled
Added subscriber-editable tags so subscribers can manage their own tag preferences in the portal
Added a re-evaluate filters after delay option for automations

Added granular API keys with per-key labels and permissions
Merged in a change to embedded checkout to allow better plexing between monthly/annual
Redesigned callouts to be less visually chaotic
Refactored firewall for improved functionality/productivity
Reorganized design settings into separate archive and email design pages
Added reusable snippets that can be inserted into emails via the / command menu
Added initial (janky) support for surveys in the archives
Added starred views for pinning pages to the sidebar
Bumped up mypy + django-stubs pretty heavily to yield some performance benefits
Added no-code archive customization — fonts, accent colors, link styling, and spacing
Added filtering to the notification inbox — All, Unread, and Needs Response views
Added Mastodon follower analytics to the dashboard
The mobile variant of dialogs now triggers at a narrower viewport
Expanded the TTL for Cleantalk responses from 3 to 30 days
Moved QR code generation serverside to fix bug where icons weren't being embedded
Migrated from ImprovMX to Cloudflare email workers for routing @buttondown.com
Disabled users are now prompted in-app to answer questions about their newsletters to help out KYC
Migrated some straggling domains' NS servers (but not ownership) from DNSimple to Cloudflare
Added two new archive themes: Arbus and Lovelace, a grid layout and a brutalist monospace option
Made custom buttons work in Markdown mode
Added Seline and Tinylytics as privacy-friendly analytics integrations for archives
Added the ability to unban subscribers directly from the UI
Added announcement bars for archive pages with markdown support and audience targeting