Important
This release addresses the security vulnerabilities PSA-2026-TD98KY and PSA-2026-P8W1J0, all users are recommended to upgrade immediately.
Highlights
This is a large release. The headline features are YouTube video clipping, a TikTok for Business provider, Sign in with Apple, a pluggable payment provider layer with RevenueCat alongside Stripe, and a much deeper MCP / agent surface (file upload widget, ChatGPT app, one-click Claude connector). Under the hood the publishing workflow gained heartbeats so hung activities are retried instead of stalling, and roughly forty provider-level bugs were fixed.
Important
This release adds new Prisma models and several new environment variables, and ships new Temporal workflow versions. See Upgrade notes before deploying.
✨ Features
Clipping — YouTube video → vertical clips → draft posts
- Video clipping workflow — paste a YouTube URL and get back captioned vertical clips that land in the media library, optionally as draft posts on selected channels (#2104)
- Choose how many clips (1–10) and how the 16:9 source lands on a vertical canvas (
croporblur) - Runs as a dedicated Temporal workflow with ingest and clipping activities on RunPod Serverless, using Deepgram to transcribe videos with no usable captions
- Exposed as MCP tools with an interactive widget, so it can be driven from Claude and ChatGPT
- Choose how many clips (1–10) and how the 16:9 source lands on a vertical canvas (
- Clipping endpoints on the public API —
POST /public/v1/clipping,GET /public/v1/clippingandGET /public/v1/clipping/:id(#2111)
New channels and channel features
- TikTok for Business provider — a separate channel type for TikTok Business accounts, with music selection, random music and location tagging (#1897, #1908)
- Provider visibility and migration controls —
HIDDEN_PROVIDERShides a provider from the add-channel screen, andMIGRATE_PROVIDERS(old:new) routes a reconnect of the old provider through the new one and migrates the channel in place - X (Twitter) articles — long-form article publishing support in the X provider and launch editor
- Farcaster: Neynar managed signers — migrated off SIWN to Neynar managed signers, fixing the broken login state; the approval QR now opens in a modal instead of a blank tab (#2078, #2080)
- Reddit subreddit search now resolves a pasted
r/nameor full subreddit URL (#2116) - Facebook background presets, Instagram collaborators and TikTok settings handling were tightened across the fix sweep below
Accounts, auth and billing
- Sign in with Apple — web sign-in via a Services ID plus
.p8key, and native mobile sign-in via the iOS bundle id - Pluggable payment providers — payment handling moved behind a provider interface and manager, with RevenueCat added next to Stripe for App Store / Google Play subscriptions from the mobile app
- Delete account — self-service account deletion from settings and from the FAQ page
- Better onboarding flow for new accounts
- Post reminders
- Repeated posts — repeat handling reworked end to end (workflow v1.1.0)
- Organization switching while impersonating (#1866)
- Clearer active account/org indication for users who have several accounts on the same email (#1814)
- Billing: the real prorated upgrade amount is shown instead of
$0(#1904), and cancellation emails now go to the customer rather than an internal address (#1782)
AI agent and MCP
- Upload widget — upload local files from Claude and ChatGPT straight into the media library (#2099)
- ChatGPT app served on its own
/mcp-oauth-chatgptissuer, with ChatGPT Enterprise domain restrictions via verified email claims - One-click Claude connector, Claude Dynamic Client Registration (RFC 7591) with a
DCR_VERIFIED_DOMAINSredirect allowlist (#2091), andclient_secret_basicaccepted on the token endpoint (#2093) - New agent tools: list posts aligned with the List Posts API (#1816), update post settings (#1877), plus clipping, video status and upload widget tools
- MCP email restrictions and localhost support for local MCP clients
Public API
PUT /public/v1/posts/:id/settings— update a post's settings (#1817)GET /public/v1/users— list the organization's users- Superuser debug endpoints —
GET /public/v1/debug/account,/debug/channels,/debug/activityand/debug/posts/:id, behind a super-admin guard, with anx-postiz-orgoverride and anx-postiz-include-deletedheader for dispute and support evidence (#2096)
Admin and analytics
- Admin stats: unique publishing/scheduled users per platform (#1843), unique publishing/scheduled channels per platform (#1849), and active orgs per post creation source (#1997)
- Admins can apply organization-level changes while impersonating, including switching orgs
Media
- Optional media normalization — when RunPod is configured, web uploads are transcoded to 1080p h264 mp4 (images downsized) in the background; the media record reports
processinguntil the normalized file replaces the original - Veo3 video generation migrated from kie.ai to EvoLink (Seedance) (#1956)
- AI video generation no longer hangs forever when the provider reports a failure (#1809)
🔧 Reliability and orchestration
- Activity heartbeats — publishing activities now heartbeat, and the post workflow was versioned forward through v1.0.7 → v1.1.2 to use them:
- Hung publishing activities now surface what they were waiting on instead of failing opaquely (#1965)
- Pending + finalize flow extended to more platforms, reducing duplicate posts when a publish is interrupted
- Non-
mainTemporal workers are now activity-only, so they no longer pick up workflow tasks (#1718) - Temporal SDK logs are routed through console so they reach Sentry (#1906)
🐛 Fixes
Facebook / Instagram / Threads
- Video and reel analytics use
video_insights, fixing a crash on a nonexistent field (#1669) - Reels metrics are requested for video post analytics (#2115)
- Graph API errors surface in page analytics instead of caching an empty result (#2098)
(#200)permission errors map to a curated message (#1892)- Channels holding a non-page token are flagged as needing reconnection (#1881)
- Meta Graph API bumped from v20.0 to v25.0 behind a shared constant (#1917, #1969)
- Instagram: collaborators are sent on the carousel container rather than child items (#2088), untaggable collaborators are reported instead of "Unknown Error" (#1876), a leading
@is stripped from handles, "Media fetch failed" (2207052) is retryable (#1900), and a missinginstagram_content_publishpermission maps to a curated message (#1914) - Threads: the OAuth authorize URL uses
threads.com(#1819), and post length is counted in UTF-8 bytes (#1946)
- Connecting a company page no longer hijacks the personal LinkedIn channel (#1767)
- Pages are listed for Content Admins, not only Super Admins (#1808)
- Analytics elements without a
timeRangeare skipped (#1769)
TikTok / YouTube
picture_size_check_failedmessage corrected and image sizes pre-checked (#1875)- YouTube: 403 forbidden upload errors map to a curated message (#1913), and the unverified-channel thumbnail error message is clearer (#1933)
- YouTube and TikTok media reads request identity encoding (#1853)
- TikTok music fix in the business provider
- Pin analytics read from
summary_metricsinstead oflifetime_metrics(#1851) - Transient "Something went wrong on our end" errors are retried (#1907)
- "Could not fetch the image" is treated as retryable (#1931)
- The anti-spam pin block is retried instead of failing with "Unknown Error" (#1962)
Reddit / Bluesky / Slack / GMB / Hashnode / X
- Reddit:
SUBREDDIT_NOEXISTis retried rather than failing the post (#1886), subreddit names are stripped of leading/trailing slashes (#1930), and the settings type accepts onlyself,link,media(#1915) - Bluesky: the underlying error surfaces when preparation keeps failing (#1929), and a 5xx login failure no longer disconnects the channel (#2084)
- Slack:
chat.postMessagefailures surface instead of the post being marked published (#2117), and video attachments are rejected at save time (#2118) - Google Business Profile: posts fail when Google returns
REJECTEDor an unconfirmedlocalPost(#1825), and Google'ssearchUrlis used as the post release URL (#2107) - Hashnode: moved to the live GraphQL endpoint and the current
publishPostschema (#2108) - X: analytics no longer crash when a timeline page has no tweets (#1765)
Posts, webhooks and platform
- Webhook payloads were always empty — the post is now resolved via a
releaseIdfallback (#2087) - Republishing a published post requires an explicit opt-in (#1841)
- Post creation is rejected on soft-deleted channels (#1921)
- Schedule-type saves carrying a past date are rejected (#1938)
- Tags are attached on post creation after creating a tag in the modal (#1830)
- Accepting a redundant invite to an organization the user already belongs to no longer errors (#1742)
- The public API returns 404 instead of 500 when deleting a missing post (#1768)
Frontend
- Duplicate "Are you sure?" dialogs after connecting a WordPress channel (#1641)
- The org switcher dropdown stays clickable above modal screens (#1815)
- The repeat interval no longer leaks between post modal opens (#1974)
- Reconnect on a custom-fields channel opened a 404 page (#2085)
- The Change Bot Picture media picker opens as a modal (#2083)
- The hardcoded 5% trend badge was removed from provider analytics (#1970)
- Mantine
Autocompletereplaced with a native input in the customer modal (React 19 ref warning) (#2094) - The Chatbase widget is hidden while the creation modal is open
📈 Observability
- Sentry gained searchable identity tags (user id, org id, Stripe customer id) on all telemetry (#1800, #1870, #1987), structured logs from the frontend and NestJS (#1918, #1977), the account email attached to bug reports instead of prompting for it (#1869), trace and session-replay sampling to stay inside quota (#2082), and no tracing on
GETrequests to the MCP streamable routes (#2100)
🧰 Developer experience
- Unit, integration, workflow and E2E test bootstrapping with ReportPortal (#2039)
- CODEOWNERS added (#1919); contributing guidelines updated for staging and for
.env.exampleenvironment variables (#1901, #1975) - PR template now enforces a detailed
# QAsection - Security policy updated with current endpoints and a dispute policy (#1858), and GAdvisory scope broadened
- Mastra and CopilotKit upgraded; packages with known security issues upgraded
docker-composeport conflict with PGAdmin fixed
Upgrade notes
Database. New Prisma models are added: Clipping, ClippingClip, and the mastra_* set backing the upgraded agent stack. Run your usual Prisma deploy step before starting the new backend.
Temporal. New post workflow versions (v1.0.7 – v1.1.2) plus new clipping, generate.video and process.media workflows ship in this release. Deploy the orchestrator so workers register them; existing in-flight executions keep running on their pinned versions.
New environment variables (all optional unless you use the feature):
| Variable | Purpose |
|---|---|
APPLE_CLIENT_ID, APPLE_SERVICE_ID, APPLE_TEAM_ID, APPLE_KEY_ID, APPLE_PRIVATE_KEY, APPLE_BUNDLE_ID
| Sign in with Apple (web via Services ID + .p8, mobile via bundle id)
|
TIKTOK_BUSINESS_CLIENT_ID, TIKTOK_BUSINESS_CLIENT_SECRET
| TikTok for Business provider |
NEYNAR_CLIENT_ID, NEYNAR_SECRET_KEY, NEYNAR_APP_FID, NEYNAR_APP_MNEMONIC, NEYNAR_SPONSOR_SIGNERS
| Farcaster via Neynar managed signers |
RUNPOD_API_KEY, RUNPOD_ENDPOINT_ID
| Optional media normalization (requires STORAGE_PROVIDER="cloudflare")
|
RUNPOD_INGEST_ENDPOINT_ID, RUNPOD_CLIPPER_ENDPOINT_ID, DEEPGRAM_API_KEY
| Video clipping (also needs RUNPOD_API_KEY, OPENAI_API_KEY, Cloudflare storage)
|
EVOLINK_API_KEY
| Seedance AI video generation (replaces the kie.ai Veo3 path) |
REVENUECAT_SECRET_KEY, REVENUECAT_WEBHOOK_SECRET, IN_APP_PURCHASE_REJECT_SANDBOX
| RevenueCat subscriptions; webhook at {BACKEND_URL}/payment/revenuecat
|
OPENAI_OAUTH_CLIENT_ID
| OAuth client for the ChatGPT app (verified email claims for Enterprise domain restrictions) |
DCR_VERIFIED_DOMAINS
| Comma-separated redirect-domain allowlist for MCP Dynamic Client Registration; unset means any client can self-register |
HIDDEN_PROVIDERS, MIGRATE_PROVIDERS
| Hide a provider from the add-channel screen / route reconnects of an old provider through a new one |
Behaviour changes to be aware of:
- Republishing an already-published post now requires an explicit opt-in.
- Post creation against soft-deleted channels, schedule saves with a past date, and Slack video attachments are now rejected rather than silently accepted.
- Meta Graph API calls moved from v20.0 to v25.0.
- Payment webhooks are now served from a generic
{BACKEND_URL}/payment/:providerroute (/payment/stripe,/payment/revenuecat); the legacy/stripewebhook route is still served, so existing Stripe configurations keep working.
Contributors
@nevo-david, @giladresisi, @egelhaus
Full Changelog: v2.23.0...v2.24.0