What's new in
SocialRouter.
Every release, every fix, every feature — documented in one place.
MCP Server refinements
- Added`get_post_status` MCP tool — agents can now poll publishing status without leaving the tool context
- Added`list_platforms` MCP tool — returns supported platforms with character limits and media constraints
- AddedStreaming responses for long-running MCP analytics queries
- Changed`create_post` tool now accepts `"optimal"` as a `scheduledAt` value, returning the predicted time in the response
- Changed`list_connections` now returns platform icon URLs and connection health status for richer agent UIs
- FixedTool call timeout on analytics queries was 10 s — extended to 60 s
- Fixed`create_post` ignoring `scheduledAt` parameter when passed as an ISO string
- FixedMCP server disconnecting after 30 min idle on Claude Desktop (keepalive now sent every 20 s)
- SecurityMCP authentication now validates token scopes per-tool — a read-only token can no longer call `create_post`
MCP Server
Let AI agents manage social media natively. Claude Desktop, Cursor, and any MCP-compatible client can now publish posts, read analytics, and manage connections through natural language.
- AddedMCP Server — full Model Context Protocol integration at `mcp.socialrouter.eu`
- AddedMCP tools: `list_connections`, `create_post`, `schedule_post`, `get_analytics`, `check_safety`, `list_posts`
- AddedClaude Desktop one-click config in the dashboard — generates the `claude_desktop_config.json` snippet
- AddedCursor, Windsurf, and any MCP-compatible client supported via standard JSON-RPC over SSE
- AddedNatural language scheduling: agents can say "post this tomorrow at 9 am CET" and `scheduledAt` is resolved correctly
- AddedMCP authentication using existing API keys — no new credentials to manage
- ChangedAPI response times improved 23% across EU regions after connection pool tuning
- ChangedPost validation errors now include a `suggestion` field with a corrected value where possible
- FixedOAuth token refresh race condition on high-concurrency requests creating duplicate refresh attempts
- FixedDashboard session timeout not triggering correctly on Safari 17
Dashboard improvements
- AddedPost preview modal before scheduling — renders a realistic preview per platform
- AddedBulk reschedule: select multiple scheduled posts and shift them forward by N hours or days
- AddedScheduled post calendar view (week and month modes)
- AddedMedia library — reuse previously uploaded images and videos without re-uploading
- ChangedConnection list now shows token expiry countdown and proactive renewal prompts
- ChangedAnalytics date range selector now accepts arbitrary start/end dates, not just preset windows
- ChangedPost editor validates character limits in real time per platform, per character
- FixedPost editor losing unsaved content on browser back navigation
- FixedConnection reconnect flow not redirecting correctly on iOS Safari
- FixedDashboard analytics charts not rendering on Firefox 121 (SVG viewBox issue)
API improvements
- Added`X-Request-ID` header on all responses — use this for support tickets and request tracing
- Added`GET /v1/posts/:id/platforms` — per-platform publishing status for a single post
- Added`GET /v1/health` endpoint returns component-level status (api, database, queue, storage)
- ChangedError responses now include a `details` array with field-level validation messages
- ChangedRate limit headers migrated to RFC 6585 standard: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`
- ChangedAll timestamps in responses now include an explicit UTC offset (`+00:00`) per ISO 8601
- Fixed`POST /v1/posts` returning 500 instead of 422 on an invalid media URL
- FixedIdempotency key collision returning the wrong cached response when two different API keys used the same key value
- Deprecated`error.message` string field — use `error.details[]` array instead. `error.message` will be removed in v1.0
Stability & performance
- FixedWebhook delivery retries now correctly apply exponential backoff (1 min → 5 min → 15 min → 1 h → 4 h)
- FixedAnalytics ingestion lag of up to 8 min during high-volume publishing windows — reduced to < 30 s
- FixedBulk queue items silently stalling when one item exceeded the media size limit
- FixedAudit log export timing out on workspaces with > 500,000 log entries
- ChangedWebhook payload size limit increased from 256 KB to 512 KB
- ChangedAudit log export now streams for large datasets instead of buffering the full result in memory
- ChangedDatabase read replicas now used for analytics queries — reduces load on primary by 40%
- SecurityInternal signing keys rotated — no user action required; existing API keys and OAuth tokens are unaffected
Safety & Links polish
- Added`DELETE /v1/links/:id` endpoint — remove a tracked link and all associated click data
- AddedSafety API `check` endpoint now accepts `dry_run: true` to validate rules without logging the check
- ChangedSafety API response now includes `ruleId` on each flag — easier to debug which custom rule fired
- ChangedLink click analytics now refreshes in real time instead of 5-minute polling
- FixedContent Safety `check` endpoint not returning flags for empty string content (should return `safe: false, flags: ["empty_content"]`)
- FixedLink shortener not preserving query parameters that contain unencoded ampersands
- FixedUTM parameters being double-encoded when appended to Instagram bio links
- FixedCustom domain links returning 404 for up to 90 s after DNS propagation — now waits for confirmation
Post-launch fixes
- FixedContent Safety module returning HTTP 200 for rule violations — should return 200 with `safe: false` body, not a misleading 2xx implied pass
- FixedModeration queue not notifying workspace admins via webhook when items were held for review
- FixedLink Management not inheriting workspace-level UTM defaults when per-post UTM params were absent
- FixedSafety rule creation returning 500 when a blocked-words list exceeded 1,000 entries
- SecuritySafety rule storage now encrypted at rest using per-workspace keys — previously used shared key
Content Safety & Link Management
Two new modules ship together: pre-publish content scanning with fully configurable moderation rules, and link management with UTM injection and click analytics.
- AddedContent Safety module — pre-publish scanning via `POST /v1/safety/check`
- AddedCustom moderation rules: blocked words, required disclaimers, tone checks, per-platform or global
- AddedPer-platform ToS compliance validation — one call checks all target platforms simultaneously
- AddedModeration queue API — hold flagged content for human review before it reaches the publish queue
- AddedLink Management module — auto-shorten URLs with custom domains or the default `sr.link` shortener
- AddedUTM parameter injection: configure defaults per workspace, override per post
- AddedClick analytics: total clicks, unique visitors, referrers, country and device breakdown
- AddedLink click webhooks — receive `link.click` events in real time
- ChangedPost validation API now returns per-platform rule results instead of a single pass/fail for the whole post
- FixedInstagram image aspect ratio validation rejecting valid 4:5 portrait crops
- FixedFacebook video duration limit check using old 240-min cap (now 241 min as per current ToS)
Connect edge cases
- Added`theme: "auto"` option on the Connect widget — detects system light/dark preference automatically
- AddedConnect widget `onError` callback — receive structured error events instead of silent failures
- ChangediOS Safari OAuth popup replaced with redirect flow — Safari blocks popups from nested iframes
- FixedConnect widget overflowing its container on screens narrower than 375 px
- FixedOAuth state mismatch error when user had multiple tabs open during the auth flow
- FixedLinkedIn OAuth failing for accounts with enforced SSO — now surfaces a clear error message
- FixedConnect widget `lang` prop not localising the "Authorise" button on first render
Token management improvements
- Added`GET /v1/connections/:id/token-info` — expiry timestamp, granted scopes, and current health status
- AddedProactive token refresh — tokens renewed 48 h before expiry rather than waiting for a failure
- Added`connection.expiring_soon` webhook event — fired 72 h before token expiry so you can prompt reconnect
- ChangedConnection `status` field now has four values: `active`, `expiring_soon`, `expired`, `revoked`
- ChangedToken refresh retries increased from 2 to 5 attempts with jittered backoff
- FixedConcurrent token refreshes for the same connection creating duplicate refresh attempts and invalidating each other
- FixedFacebook Pages token not inheriting the right page scope when the user managed > 10 pages
Connect stability
- FixedWebhook `connection.revoked` event not firing for revocations initiated from the platform side (e.g. user removing app from Twitter settings)
- FixedConnect redirect URI validation rejecting valid subdomains with hyphens (e.g. `my-app.example.com`)
- FixedOAuth flow failing for X (Twitter) accounts with hardware security key 2FA
- Fixed`GET /v1/connections` returning stale `status: "active"` for revoked connections for up to 10 min
- ChangedOAuth PKCE code challenge now always uses S256 — plain method removed
Connect — embedded OAuth
Drop a fully branded OAuth flow into your product without building it yourself. Your users authorise their social accounts inside your UI, and SocialRouter handles every platform's auth quirks.
- AddedConnect module — embeddable OAuth widget (`<SocialRouterConnect />` React component)
- AddedCustom OAuth appearance: your logo, primary colour, button text, and redirect URL
- AddedHeadless mode — implement your own UI using the `POST /v1/connect/start` and `GET /v1/connect/callback` primitives
- AddedConnection health monitoring with automated reconnect prompts sent to your webhook endpoint
- AddedWebhook events: `connection.created`, `connection.revoked`, `connection.expired`, `connection.refreshed`
- AddedConnection list API with platform, display name, avatar URL, status, and expiry metadata
- ChangedToken storage migrated to per-tenant AES-256 encryption keys
- FixedFacebook long-lived token refresh firing 2 h early due to clock skew
- SecurityOAuth state parameter now includes a per-session CSRF nonce, validated on callback
Social Inbox improvements
- AddedInbox filtering by platform, item type (comment / mention / DM), read status, and date range
- Added`POST /v1/inbox/:id/archive` — archive items without deleting; excluded from default list
- AddedBulk mark-as-read: `PATCH /v1/inbox/read` accepts an array of item IDs
- AddedInbox items now include media attachments (images, video thumbnails) in the response
- Added`inbox.new_item` webhook event — real-time notification when new comments or DMs arrive
- ChangedInbox initial sync now fetches 90 days of history instead of 30 on first connection
- FixedInstagram DMs not appearing in inbox for business accounts using the new Messaging API
- FixedInbox reply for Twitter/X threads attaching reply to wrong parent tweet when thread was > 5 deep
Webhook reliability
- AddedWebhook delivery dashboard endpoint: `GET /v1/webhooks/endpoints/:id/stats` (success rate, avg latency, last 100 deliveries)
- AddedManual retry: `POST /v1/webhooks/deliveries/:id/retry` — replay any delivery without re-triggering the source event
- Added`GET /v1/webhooks/deliveries` — paginated history of all delivery attempts with HTTP status and response body
- ChangedExponential backoff ceiling increased from 1 h to 4 h — gives more time for temporary endpoint outages to recover
- ChangedDelivery log response body capture increased from 1 KB to 8 KB
- FixedSignature verification failing for payloads > 64 KB due to off-by-one in the HMAC body reader
- FixedWebhooks endpoint returning 200 for `POST /v1/webhooks/endpoints` when the target URL was unreachable (now validates reachability on creation)
Post-launch fixes
- FixedWebhook endpoint creation accepting `http://` URLs in production — now requires HTTPS
- FixedSocial Inbox not syncing mentions older than 7 days during initial connection sync
- FixedInbox `GET /v1/inbox` returning items from disconnected platforms
- SecurityWebhook secrets now require a minimum of 32 characters — creation returns 422 for shorter secrets. Existing short secrets will be auto-regenerated on next rotation
Webhooks & Social Inbox
Real-time event delivery with durable retries, and a unified inbox API for comments, mentions, and DMs across every connected platform.
- AddedWebhooks module — durable delivery with 72-hour retry window and guaranteed at-least-once semantics
- AddedHMAC-SHA256 payload signing — verify every event came from SocialRouter with a shared secret
- Added18 event types: `post.*`, `connection.*`, `analytics.*`, `inbox.*`, `safety.*`
- AddedDelivery logs with full HTTP request and response capture, latency, and retry history per attempt
- AddedSocial Inbox API — `GET /v1/inbox` returns comments, mentions, and DMs from all connected platforms
- Added`POST /v1/inbox/:id/reply` — reply to any inbox item from a single endpoint regardless of platform
- ChangedEvent payload schema standardised across all platforms (breaking change for 0.5 webhooks preview users)
- FixedLinkedIn `post.published` event firing before the post was actually visible on the platform
Analytics data quality
- ChangedMetrics refresh cadence reduced from 6 h to 1 h for posts published in the last 48 h
- ChangedAnalytics API default timeframe changed from `7d` to `30d` — better reflects typical review cycles
- FixedFollower count metric showing cumulative daily delta instead of absolute current count
- FixedLinkedIn impression metrics returning `null` for text-only posts (correct value now returned)
- FixedAnalytics export including duplicate rows for posts published to multiple platforms simultaneously
- FixedTikTok view counts off by a factor of 1,000 — platform API returns views-per-mille in some responses; now normalised to absolute counts
Advanced scheduling
- AddedRecurring post schedules: daily, weekly, monthly, or a custom CRON expression
- AddedScheduling blackout windows — define hours or days when posts should never be sent (useful for weekends, holidays)
- Added`GET /v1/schedule/suggestions` — returns per-account optimal time slots for the next 7 days
- AddedBatch scheduling: `POST /v1/posts/batch` accepts up to 500 posts in a single request with independent `scheduledAt` per item
- Changed`scheduledAt: "optimal"` now returns the resolved predicted time in the API response body
- FixedPosts scheduled for times within a DST transition failing to publish due to ambiguous local time resolution
- FixedRecurring schedule next-occurrence calculation skipping a week after months with 31 days
Analytics fixes
- FixedEngagement rate calculation dividing by total followers instead of post reach — rates were vastly understated for viral posts
- FixedAnalytics API returning 504 for accounts with > 1,000 posts in the query window — query is now chunked and streamed
- Fixed`GET /v1/analytics/aggregate` returning different totals on consecutive calls for the same date range (race condition in cache invalidation)
- ChangedAnalytics endpoints now accept `platform[]` as a multi-value query param to filter by multiple platforms in one call
Analytics & Smart Scheduling
Engagement metrics across all platforms, plus an ML model that predicts the best time to post for each connected account based on historical performance.
- AddedAnalytics module — reach, impressions, engagement rate, follower growth, link clicks per post and account
- AddedSmart Scheduling — ML model trained on per-account historical engagement predicts optimal posting windows
- Added`GET /v1/analytics/posts/:id` — full per-platform breakdown for a single post
- Added`GET /v1/analytics/accounts/:id/summary` — rolling 30-day performance summary
- AddedAnalytics data export as CSV or JSON via `GET /v1/analytics/export`
- AddedAggregated analytics across multiple connections in a single query
- Changed`POST /v1/posts` now accepts `"scheduledAt": "optimal"` — the API picks the best time automatically
- FixedTimezone offset applied twice when scheduling posts in non-UTC timezones via the dashboard
- FixedLinkedIn analytics not returning video view counts for Carousel posts
Bulk & media fixes
- FixedBulk queue items stuck in `queued` state after a worker restart — items now re-picked up within 60 s
- Fixed4K video uploads failing for files > 2 GB — upload endpoint now uses a streaming multipart parser
- FixedContent Adaptation stripping emoji from Instagram captions when adapting from LinkedIn source
- FixedBulk status endpoint returning the full post body for each item — now returns a summary with `id`, `status`, `platform`, and `error` only (reduces response size by ~90%)
- ChangedBulk status `GET /v1/posts/batch/:batchId/status` now supports `?since=` cursor for efficient incremental polling
- ChangedPinterest and TikTok rate limits now factored into the bulk queue scheduler — no more silent 429 failures
Platform improvements
- AddedPinterest: board selection field when creating Pins — `board_id` parameter on `POST /v1/posts`
- AddedTikTok: `privacy_level` field (`public`, `friends`, `private`) and `allow_comments` toggle
- AddedYouTube: chapter markers — include timestamps in the video description and they are parsed as chapters automatically
- AddedInstagram: `collaborator_tags` field for collaborative posts with other accounts
- FixedInstagram carousel ordering not preserved after Content Adaptation reordering pass
- FixedFacebook group posting permission check returning false positive — posts were queued and then failed at publish time
- FixedYouTube thumbnail upload silently discarding images with an alpha channel — now auto-converts to JPEG
Content Adaptation polish
- AddedContent Adaptation now generates platform-native alt text for media attachments using the post caption as context
- ChangedLinkedIn character limit used during adaptation corrected from 700 to 3,000
- ChangedHashtag deduplication now preserves intentionally repeated hashtags (previously collapsed all duplicates)
- FixedThreads adaptation not preserving line breaks from the source post
- FixedYouTube adaptation not appending the required `#Shorts` tag for videos under 60 s
- Deprecated`adapt_content: true` boolean field on `POST /v1/posts` — use the `adaptation: { enabled: true, options: {} }` object instead. The boolean will be removed in v1.0
Bulk Operations & Content Adaptation
Queue thousands of posts in a single API call, and let SocialRouter automatically reformat your content natively for each target platform.
- AddedBulk Operations API — `POST /v1/posts/batch` accepts up to 10,000 posts in one request
- AddedBuilt-in per-platform rate limiting inside the bulk queue — no 429 errors to handle yourself
- AddedBatch status endpoint: `GET /v1/posts/batch/:batchId/status` with per-item results
- AddedContent Adaptation — set `adaptation: { enabled: true }` and one source post is reformatted natively for every target platform
- AddedTikTok and Pinterest adapters (platform count now 11)
- AddedMedia upload now supports up to 4K resolution with automatic transcoding to platform requirements
- ChangedPost `status` field expanded: `draft`, `queued`, `publishing`, `published`, `failed`, `cancelled`
- RemovedLegacy `/v0/publish` endpoint removed after 60-day deprecation period — use `POST /v1/posts`
Bluesky & Threads improvements
- AddedBluesky `reply_ref` field for threading replies to specific posts
- AddedBluesky rich text: URLs, mentions, and hashtags in the post body are now auto-linked in the published post
- ChangedThreads rate limit window corrected from 24 h to 1 h to match the actual platform API behaviour
- FixedBluesky posts exceeding 300 characters failing silently — now returns a clear 422 with `character_limit_exceeded`
- FixedThreads media posts not appearing in feed despite receiving a 200 response from the platform API
- FixedBluesky image alt text not being attached to posts when set via the API
API hardening
- AddedRequest idempotency keys — include `Idempotency-Key: <uuid>` on any POST endpoint to safely retry without duplicates
- Added`GET /v1/health` for load balancer health checks — returns 200 if all components healthy, 503 otherwise
- ChangedAll timestamps now returned as ISO 8601 with an explicit UTC offset — `2025-07-18T14:30:00+00:00` instead of `2025-07-18T14:30:00Z`
- FixedConcurrent `POST /v1/posts` calls with identical content and `scheduledAt` creating duplicate posts
- SecurityInput validation tightened across all text fields — HTML tags stripped, control characters rejected, length limits enforced at the API boundary
Developer experience
- AddedOpenAPI 3.1 spec published at `GET /openapi.json` — kept in sync with every release
- AddedOfficial Node.js and Python SDKs (alpha) — `npm install @socialrouter/sdk` / `pip install socialrouter`
- AddedPostman collection and Bruno collection in the documentation
- AddedAPI Playground at `api.socialrouter.eu/playground` — test calls in the browser against your live API key
- ChangedAPI error codes standardised to machine-readable strings: `rate_limit_exceeded`, `invalid_media_url`, `platform_auth_failed`, etc.
- FixedAPI reference docs showing incorrect `Authorization: Bearer` format — correct format is `X-API-Key: sr_...`
Platform expansion & API v1
Stable, versioned API. Three new platform adapters. Audit logging. The foundation everything else is built on.
- AddedYouTube, Threads, and Bluesky adapters (platform count now 8)
- AddedAPI v1 — stable, versioned REST API with a published deprecation and semver policy
- AddedAPI key management: create, name, scope, and revoke keys from `GET/POST/DELETE /v1/api-keys`
- AddedScoped API key permissions: `posts:read`, `posts:write`, `connections:read`, `analytics:read`, `admin`
- AddedAudit logging — every API call, authentication event, key creation, and configuration change is logged
- Added90-day audit log retention on Starter, 12-month on Business, 7-year immutable on Enterprise
- ChangedAuthentication supports JWT and API key simultaneously in the same request context
- FixedTwitter/X rate limit errors now trigger exponential backoff automatically instead of immediately failing the request
- SecurityAPI keys now stored as bcrypt hashes — the plaintext is shown once on creation and never stored
Performance & reliability
- ChangedDatabase connection pooling retuned — p99 API latency reduced by 40% under sustained load
- ChangedMedia uploads migrated from base64 JSON body to chunked multipart — allows files > 10 MB without memory issues
- FixedInstagram token refresh silently failing for connections older than 60 days
- FixedDashboard connection list not paginating beyond the first 25 items
- Fixed`POST /v1/posts` occasionally returning 200 but not enqueuing the post when the task queue was under pressure
- SecuritySecurity headers added to all responses: `Strict-Transport-Security`, `X-Frame-Options: DENY`, `Content-Security-Policy`
Dashboard improvements
- AddedPost history with filtering by platform, status, and date range
- AddedScheduled post calendar view (week and month modes)
- AddedMedia library — upload once, reuse across multiple posts without re-uploading
- AddedTeam member invitation flow — invite collaborators with read-only or full-access roles
- ChangedPost editor now shows per-platform character count in real time and highlights the over-limit text
- FixedDashboard login session not persisting correctly when the same account was open in multiple browser tabs
Launch fixes
- FixedFacebook OAuth callback failing for Pages with special characters (apostrophes, accented letters) in their name
- FixedTwitter/X image upload returning HTTP 200 with a failed upload body — now correctly returns 422
- Fixed`scheduledAt` silently discarding milliseconds, causing posts to be scheduled 0–999 ms early
- Fixed`GET /v1/posts/:id` returning 404 for posts in the `publishing` state (transitional state now included)
- ChangedPlatform authentication errors now return a structured error with `platform`, `error_code`, and `suggested_action` fields instead of a generic 500
Core platform
The first complete version: four major platforms, scheduling, OAuth connection management, and a web dashboard.
- AddedLinkedIn, Facebook, Instagram, and Twitter/X adapters
- AddedPost scheduling: `scheduledAt` accepts any future ISO 8601 datetime with timezone
- AddedOAuth connection management — `GET/POST/DELETE /v1/connections`
- AddedDashboard at `dashboard.socialrouter.eu` — manage connections, create posts, view history
- AddedUser registration, email verification, and password-based authentication
- AddedTeam management — invite members, assign roles, revoke access
- AddedAPI documentation published at `docs.socialrouter.eu`
- AddedStarter, Business, and Enterprise pricing tiers with metered connected-account billing
Infrastructure hardening
- AddedAzure Amsterdam (West Europe) configured as hot failover for Frankfurt primary region
- AddedAutomated database backups every 6 hours with 30-day point-in-time restore retention
- AddedBasic rate limiting: 60 req/min per API key, 429 with `Retry-After` header on breach
- ChangedAll secrets (DB passwords, JWT signing keys, OAuth credentials) migrated from config files to Azure Key Vault
- FixedAPI returning HTTP 200 with an error body for several error conditions — now returns correct 4xx/5xx codes
- SecurityTLS 1.0 and TLS 1.1 disabled on all endpoints — TLS 1.2 minimum, TLS 1.3 preferred
First patch
- AddedBasic structured request logging for post-launch debugging
- ChangedBeta tester rate limits raised from 10 req/min to 60 req/min
- FixedLinkedIn post creation failing for personal profiles — was only working for Company Pages
- FixedAPI key generation form not working in Firefox 124 (missing `crypto.randomUUID` polyfill)
- Fixed`POST /v1/posts` returning a 201 with an empty response body — now returns the created post object
Private beta
The beginning. One endpoint. One platform. EU infrastructure from day one.
- AddedUnified social API concept — one REST endpoint targeting multiple platforms
- AddedLinkedIn adapter as the first proof of concept
- AddedEU-only infrastructure — primary region Frankfurt (Germany West Central) on Microsoft Azure
- AddedJWT-based authentication (API keys come in v0.3)
- AddedDeveloper documentation (draft, covers LinkedIn publishing only)
- AddedPrivate beta sign-up at `socialrouter.eu`