v2.24.0
gitroomhq/postiz-appv2.24.0Sep 22, 2026by egelhaus
Upgrading?
AI Summary
This major release introduces YouTube video clipping, a dedicated TikTok for Business provider, Sign in with Apple, and a pluggable payment provider layer with RevenueCat. It significantly deepens the MCP/agent surface and improves reliability through activity heartbeats and workflow updates.
Key Highlights
- YouTube video clipping workflow with Deepgram transcription and MCP tools
- TikTok for Business provider with music selection and location tagging
- Sign in with Apple authentication
- RevenueCat integration for mobile subscriptions
- Enhanced MCP/Agent surface with ChatGPT app and file upload widget
- Activity heartbeats to prevent hung publishing workflows
Breaking Changes
- Republishing an already-published post now requires an explicit opt-in
- Post creation against soft-deleted channels, past-date schedules, and Slack video attachments are now rejected
- Meta Graph API calls moved from v20.0 to v25.0
- Payment webhooks route changed to generic `/payment/:provider`
New Features
- YouTube video clipping workflow and public API endpoints
- TikTok for Business provider
- Sign in with Apple
- RevenueCat payment integration
- ChatGPT app and Claude connector
- File upload widget for MCP agents
- Farcaster Neynar managed signers
- Admin stats for platform analytics
- Optional media normalization via RunPod
- X (Twitter) article publishing support
- Reddit subreddit search
- Admin impersonation features
Full Release Notes
> [!IMPORTANT]
> This release addresses the security vulnerabilities [PSA-2026-TD98KY](https://gadvisory.org/advisories/PSA-2026-TD98KY) and [PSA-2026-P8W1J0](https://gadvisory.org/advisories/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](#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 (`crop` or `blur`)
- 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
- **Clipping endpoints on the public API** — `POST /public/v1/clipping`, `GET /public/v1/clipping` and `GET /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_PROVIDERS` hides a provider from the add-channel screen, and `MIGRATE_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/name` or 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 `.p8` key, 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-chatgpt` issuer, with ChatGPT Enterprise domain restrictions via verified email claims
- **One-click Claude connector**, Claude **Dynamic Client Registration** (RFC 7591) with a `DCR_VERIFIED_DOMAINS` redirect allowlist (#2091), and `client_secret_basic` accepted 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/activity` and `/debug/posts/:id`, behind a super-admin guard, with an `x-postiz-org` override and an `x-postiz-include-deleted` header 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 `processing` until 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:
- v1.0.7/v1.0.8 introduce and fix heartbeating
- v1.0.9 removes the fixed interval
- v1.1.0 reworks repeat handling
- v1.1.1 retries activities that never started on a heartbeat timeout (#1996)
- v1.1.2 also retries on a heartbeat timeout with no heartbeat details (#2013)
- **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-`main` Temporal 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 missing `instagram_content_publish` permission 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)
### LinkedIn
- 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 `timeRange` are skipped (#1769)
### TikTok / YouTube
- `picture_size_check_failed` message 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
### Pinterest
- Pin analytics read from `summary_metrics` instead of `lifetime_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_NOEXIST` is retried rather than failing the post (#1886), subreddit names are stripped of leading/trailing slashes (#1930), and the settings type accepts only `self`, `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.postMessage` failures 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 `REJECTED` or an unconfirmed `localPost` (#1825), and Google's `searchUrl` is used as the post release URL (#2107)
- Hashnode: moved to the live GraphQL endpoint and the current `publishPost` schema (#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 `releaseId` fallback (#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 `Autocomplete` replaced 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 `GET` requests 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.example` environment variables (#1901, #1975)
- PR template now enforces a detailed `# QA` section
- 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-compose` port 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/:provider` route (`/payment/stripe`, `/payment/revenuecat`); the legacy `/stripe` webhook route is still served, so existing Stripe configurations keep working.
## Contributors
@nevo-david, @giladresisi, @egelhaus
**Full Changelog**: https://github.com/gitroomhq/postiz-app/compare/v2.23.0...v2.24.0
Related Repositories
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
Interactive roadmaps, guides and other educational content to help developers grow in their careers.
Reverse engineer anything with agents, from app behavior down to native binaries.
The open source coding agent.
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.