v2.24.0

siteboon/claudecodeuiv2.24.0Sep 22, 2026by egelhaus

Upgrading?

AI Summary

This is a major release adding YouTube video clipping, TikTok for Business provider, Sign in with Apple, and a pluggable payment provider layer with RevenueCat, while improving the MCP/agent surface and adding activity heartbeats for reliability.

Key Highlights

  • YouTube video clipping workflow with captioned vertical clips
  • TikTok for Business provider with music selection and location tagging
  • Sign in with Apple authentication
  • Pluggable payment providers with RevenueCat integration
  • Activity heartbeats to prevent hung publishing activities

New Features

  • YouTube video clipping workflow with Deepgram transcription
  • TikTok for Business provider
  • Sign in with Apple authentication
  • Pluggable payment provider layer with RevenueCat
  • Upload widget for file uploads from Claude and ChatGPT
  • ChatGPT app with Enterprise domain restrictions
  • One-click Claude connector with Dynamic Client Registration
  • Admin stats for unique publishing/scheduled users per platform
  • Optional media normalization with RunPod transcoding
  • Activity heartbeats and improved retry logic

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