> ## Documentation Index
> Fetch the complete documentation index at: https://docs.smartlyq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> New endpoints, improvements, and fixes to the SmartlyQ API

Product updates for the SmartlyQ Developer API, MCP server, and Developer Portal. All endpoints live at `https://api.smartlyq.com/v1`.

<Update label="July 27, 2026" tags={["WhatsApp", "New"]}>
  ## WhatsApp Business messaging (Phase 1)

  SmartlyQ now connects to the **WhatsApp Business Cloud API**:

  * **Connect** a WhatsApp Business number - `POST /social/connect/whatsapp` with `{ waba_id, phone_number_id, access_token }`.
  * **Send** - `POST /whatsapp/messages`: text and media (session messages, inside the 24-hour window) and approved templates (any time).
  * **Receive** - inbound messages and delivery receipts arrive on your webhooks and populate the in-app Inbox. New events: `message.delivered`, `message.read`, `message.failed` (joining `message.received`).
  * **Manage** - list/create message templates (`/whatsapp/templates`), read/update the business profile (`/whatsapp/business-profile`), and list phone numbers (`/whatsapp/phone-numbers`).

  See the new [WhatsApp guide](/guides/whatsapp). Flows, calling, groups and interactive buttons are planned for a later phase.
</Update>

<Update label="July 27, 2026" tags={["Social", "New"]}>
  ## X reply threads with media

  `first_comments` on X now post as a **chained reply thread** (the first replies to the post, each next one to the previous), and any entry can attach media: pass `{ "text": "...", "media_urls": ["https://..."] }` instead of a plain string to put up to 4 images on that reply. Same in the app composer - first comments on X now offer image **and video** attachment (one video per reply, X's limit). See [Platform options](/guides/platform-options#x-twitter).
</Update>

<Update label="July 27, 2026" tags={["Social", "Fixed"]}>
  ## X (Twitter) comment threads, and more

  * **X comment threading fixed** - replies on X posts now nest correctly. Previously the reply tree never linked (we keyed on the replied-to user instead of the parent tweet), so X threads came back flat. Reply nesting now works for every platform except Pinterest (whose comments are inherently flat). This fix applies to the app's comment view as well as the API.
  * **`GET /social/comments/{post_id}`** - fetch one post's comments as a nested thread by id, instead of filtering the full comments list.
  * **`PUT` / `DELETE /contacts/{id}/fields/{slug}`** - set or clear a single contact custom field by its slug, without sending the whole attributes object.
  * **`GET /me/billing`** - a read-only superset of `/me/balance`: balance breakdown, monthly cycle reset, auto-recharge config, and card-on-file status with an at-a-glance `payment.status`.
</Update>

<Update label="July 27, 2026" tags={["API", "New"]}>
  ## Profile update and direct media upload

  * **`PATCH /profiles/{id}`** - rename a profile or change its `external_id` without recreating it (renaming keeps the backing workspace name in sync). Fills the last gap in profile management.
  * **`POST /media/upload-direct`** - upload a file in a single `multipart/form-data` request, no presign round-trip. Stored straight to your media library and returned in the same shape as `GET /media/{id}`; the type is detected from the file's actual bytes, up to 200MB.
</Update>

<Update label="July 27, 2026" tags={["Webhooks", "New"]}>
  ## 10 new webhook events

  The event catalog grows from 25 to 35, covering lifecycle moments you could already act on internally but couldn't subscribe to:

  * **Posting** - `post.scheduled` (a post was queued for later), `post.cancelled` (a scheduled post was deleted before publishing), `post.recycled` (a recycling chain spawned its next occurrence), and `post.external.created` / `post.external.updated` for posts authored natively on the platform and picked up by external sync.
  * **Inbox** - `message.sent` (outbound DM delivered), `conversation.started` (a new thread opened), `reaction.received` (an emoji reaction added or removed).
  * **Reviews** - `review.new` and `review.updated` for Google Business reviews and replies.

  All fire from both the app and the API where applicable, carry the same signed, deduplicatable envelope as every other event, and are subscribable from the dashboard, the API, and MCP. See the [Webhooks guide](/guides/webhooks).
</Update>

<Update label="July 27, 2026" tags={["Social", "New"]}>
  ## Idempotent creates, per-platform stagger, richer platform options

  * **Idempotency keys** - send `X-Idempotency-Key` (or `X-Request-Id`) on `POST /social/posts` / `/schedule`; a retry with the same key returns the original post (`200`, `idempotent_replay: true`) instead of double-posting. Backed by a unique constraint, so even concurrent retries can't create twice. Works alongside the existing 24-hour duplicate-content guard (`409 DUPLICATE_CONTENT` + `allow_duplicates`). New [Idempotency guide](/guides/idempotency).
  * **Per-platform stagger** - on the schedule endpoint, any platform can carry its own `scheduled_time` inside `platform_options`: one call, each network publishing at its own moment (response lists the created `staggered[]` legs).
  * **Platform options, documented and extended** - new [Platform options guide](/guides/platform-options) covering every per-platform key. Newly added: Telegram `parse_mode`/`silent`/`disable_link_preview`/`protect_content`, Reddit `flair_id`/`flair_text`, YouTube `tags`/`category_id`/`contains_synthetic_media` (AI disclosure), Instagram `share_to_feed` for Reels.
</Update>

<Update label="July 27, 2026" tags={["Social", "New"]}>
  ## Connect Telegram by API, Discord headlessly

  Every platform can now be connected without the SmartlyQ dashboard:

  * **Telegram credential connect** - `POST /social/connect/telegram` with `{ "bot_token", "chat" }` connects the channel immediately (Telegram has no OAuth; this is the same verify-then-save flow as the dashboard modal: bot verified with Telegram, posting rights required, private chats rejected, plan limit enforced, token encrypted at rest). Built for agencies automating workspace onboarding.
  * **Discord headless connect** - `POST /social/connect/discord` mints the server-webhook authorize URL like any OAuth platform.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Telegram and Discord publishing

  Two new `platforms` targets on `POST /social/posts` and `POST /social/posts/schedule`:

  * **`telegram`** - publishes through your own bot (created with [@BotFather](https://t.me/BotFather)) to its channel or group: text up to 4,096 characters, single media or 2-10-item albums sent by URL. Connected from the dashboard's Social Accounts page.
  * **`discord`** - publishes through a channel webhook on your server: text up to 2,000 characters, up to 10 images as embeds, posting under your workspace brand's name and logo when one is set.

  Both platforms respect the same pre-publish validation, auto-transcode, progress states, and webhook events as every other target. Discord also supports [headless connect](/guides/connecting-accounts) (`POST /social/connect/discord`) - its server-webhook authorize flow works from your own UI like any OAuth platform. See the new [Telegram](/platforms/telegram) and [Discord](/platforms/discord) platform pages.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Auto-transcode, publish progress, and exact failure reasons

  One `POST /social/posts` call now does more of the hard work invisibly:

  * **Auto-transcode** - media that a platform would reject for a fixable reason is converted automatically before publishing: video that isn't H.264/AAC MP4 is re-encoded (web-optimized, moov-front), frame rates are brought into each platform's documented range (raised to 30fps below TikTok/Instagram's 23fps floor, capped at 60fps), oversize videos are shrunk under the platform's byte cap, and images in formats a platform rejects are converted (e.g. WEBP to PNG for LinkedIn). What was fixed is reported per platform in the post's `post_urls._transcodes` and in the `transcoded[]` list on `post.published` / `post.partial` / `post.failed` webhook payloads. Changes that would alter your content - trimming duration, cropping aspect ratios - are never made automatically; those still return a precise error telling you what to change.
  * **Publish progress** - posts now expose `publish_stage` (`validating` → `processing_media` → `publishing`) while a publish is running, so `GET /social/posts/{id}` shows where a slow publish is instead of a bare `processing`.
  * **Exact failure reasons, end to end** - a failed post always carries its reason now: whole-post failures persist an explanation in `post_urls._errors`, immediate (non-scheduled) posts store per-platform permalinks and errors just like scheduled ones, and webhook failure payloads include `error.detail` with the exact pre-publish reason (e.g. `"Twitter/X caption is 312 characters; the limit is 280. Trim 32 characters and retry."`) whenever the failure came from SmartlyQ's own checks.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Rich DMs, comment-to-DM automations, connection selection, deep insights

  * **Structured DMs** - `POST /social/conversations/{id}/messages` now takes `buttons` (Facebook button template, up to 3 links) and `quick_replies` (Facebook + Instagram chips, up to 13), plus a typing indicator at `POST .../typing`.
  * **Comment-to-DM** - `POST /social/comments/{comment_id}/private-reply` DMs the comment's author (Meta private replies, FB + IG). New `comment_created` automation trigger + `action.private_reply` runner action: build "comment X gets an automatic DM" flows in the automation builder.
  * **Messaging surfaces** - Messenger persistent menu and Instagram ice breakers, full CRUD under the account.
  * **Connection selection** - `GET .../connect-options` + `POST .../connect-select` re-point a Google Business connection at any location of its parent account; platforms with entity-bound tokens report why they can't switch without reconnect.
  * **Deep insights** - `GET .../facebook/page-insights` (any Meta page metric, passthrough) and `GET .../instagram/audience` (follower demographics by city/country/age/gender).
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Subreddit eligibility, X mentions, contact channels

  * **Subreddit check** - `GET /social/accounts/{account_id}/reddit/subreddits/{subreddit}` returns the community's rules of engagement plus a computed `can_post` verdict for your connected account (banned? restricted? what submission kinds?).
  * **X mentions** - `GET /social/accounts/{account_id}/x/mentions` lists recent posts mentioning the account, with engagement metrics.
  * **Contact channels** - `GET /contacts/{id}/channels` shows which channels a contact actually communicates on, with volume and last activity.
  * **Custom field update** - `PATCH /custom-fields/{id}` edits a field definition (the key stays immutable).
  * **Place-action update** - `PATCH /social/accounts/{account_id}/gmb/place-actions` changes a link's URI in place.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Google Business Profile management

  Sixteen endpoints under `/social/accounts/{account_id}/gmb/*`, riding the connection's existing permissions: list all locations, read and update business info (hours, phone, categories, description) with field masks, manage attributes (with a metadata endpoint that tells you what this location supports), publish and remove photos, edit structured food menus, manage place-action links (order/reserve/appointment), and inspect verification state and options. Bodies are passthroughs of Google's resource shapes - every Google field works without waiting for us.
</Update>

<Update label="July 26, 2026" tags={["Webhooks", "Fixed"]}>
  ## Webhooks scopes are now grantable

  The `/webhooks` endpoints require the `webhooks:read` / `webhooks:write` scopes - but the key-creation surfaces never offered them, so freshly created keys received `403 INSUFFICIENT_SCOPE` on every webhook call. The scope picker in the Developer Dashboard (and the OAuth catalog) now includes both. **Existing keys are unchanged**: edit your key's scopes or create a new key to pick up webhook access.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Edit published posts, external sync, live insights

  * **Edit published** - `POST /social/posts/{post_id}/edit` edits the post natively on the platform. Facebook works today; X (paid-tier API) and Reddit (extra scope) report unsupported per platform instead of failing.
  * **YouTube metadata** - `POST /social/posts/{post_id}/update-metadata` updates title/description/tags, adds to a playlist, and sets a custom thumbnail after publish.
  * **External post sync** - `POST /social/posts/sync-external` imports posts published natively on Facebook, Instagram, Threads, YouTube or TikTok (per-account opt-in); they appear in `GET /social/posts?status=external` with analytics.
  * **Live account insights** - `GET /social/accounts/{account_id}/insights` returns platform-fresh follower/impression/reach/engagement metrics for every provider-backed platform.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Per-platform post options, X retweets, story insights, safe retries

  * **platform\_options** - create, schedule, and bulk rows now accept the same per-platform options object the web composer uses: TikTok privacy/duet/stitch, per-platform caption overrides, custom video thumbnails, and more. Publish handlers consume it directly.
  * **X engagement** - `POST /social/accounts/{account_id}/x/retweets` and its DELETE counterpart retweet/un-retweet with the connected account.
  * **Story insights** - `GET .../instagram/stories/{story_id}/insights` with a passthrough `metrics` parameter.
  * **Delete review reply** - `DELETE /reviews/{review_id}/reply` removes the reply on Google Business.
  * **Idempotency, documented** - every write endpoint has always honored `X-Idempotency-Key` (24h replay window, never double-billed); it is now documented in the API intro.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Reddit research tools, Instagram stories, Facebook reactions

  * **Reddit** - four research endpoints under `/social/accounts/{account_id}/reddit/`: `search` (optionally restricted to a subreddit), `feed` (hot/new/top/rising), `subreddits` (your subscriptions), and `subreddits/{subreddit}/rules` - check the rules before you submit.
  * **Instagram stories** - `GET /social/accounts/{account_id}/instagram/stories` lists the account's currently live stories.
  * **Facebook reactions** - `GET /social/accounts/{account_id}/facebook/post-reactions` returns the per-type breakdown (like, love, wow, haha, sad, angry, care) for any published post.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Per-platform lookups

  Five account-level lookups so integrations can compose with real platform data - all `social:read`:

  * **Pinterest boards** - `GET /social/accounts/{account_id}/pinterest/boards`
  * **YouTube playlists** - `GET /social/accounts/{account_id}/youtube/playlists`
  * **Instagram publishing limit** - `GET /social/accounts/{account_id}/instagram/publishing-limit` (daily quota total/remaining)
  * **Google Business performance** - `GET /social/accounts/{account_id}/gmb/performance?days=28` (impressions by surface, deltas, daily series)
  * **Google Business search keywords** - `GET /social/accounts/{account_id}/gmb/search-keywords`
</Update>

<Update label="July 26, 2026" tags={["CRM", "New"]}>
  ## Automations API + contact bulk import

  * **Operate your automations** - new `/automations` group: list and inspect automations built in the visual builder, activate/pause them, queue a manual run with `POST /automations/{automation_id}/trigger` (optional JSON payload), and read run history down to per-step execution logs.
  * **Bulk import** - `POST /contacts/bulk` imports up to 100 contacts through the same email/phone upsert as single create - re-importing a file is idempotent, with per-row created/updated/failed results.
  * **Delete** - `DELETE /contacts/{id}` soft-deletes (recoverable from Deleted contacts in the app).
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Inbox: search, detail, archive

  * **Search** - `GET /social/conversations/search?q=` scans participant names and message content across the whole inbox and returns the latest matching message per conversation.
  * **Detail** - `GET /social/conversations/{conversation_id}` adds a single-conversation view with incoming/outgoing counts.
  * **Archive** - `PATCH /social/conversations/{conversation_id}` with `{ "status": "archived" }` (or `"open"` to restore).
  * **Drill-down analytics** - `GET /analytics/inbox/conversations` (+ `/{conversation_id}`) closes out the inbox analytics suite with per-conversation volume and response times.
</Update>

<Update label="July 26, 2026" tags={["Reviews", "New"]}>
  ## Reviews API

  Reputation Management is now scriptable:

  * **List** - `GET /reviews` with rating / reply-status / account filters.
  * **Reply** - `POST /reviews/{review_id}/reply` publishes your reply on Google Business.
  * **Sync** - `POST /reviews/sync` pulls fresh reviews on demand, per account or workspace-wide.
</Update>

<Update label="July 26, 2026" tags={["Analytics", "New"]}>
  ## Inbox analytics

  Five endpoints under `/analytics/inbox/*` (all `analytics:read`, unbilled): daily volume with new-conversation counts, a weekday x hour incoming-message heatmap in your timezone, per-platform source breakdown, first-response times (average, median, histogram from under 15 minutes to over 24 hours), and your busiest accounts.
</Update>

<Update label="July 26, 2026" tags={["Analytics", "New"]}>
  ## Analytics that answer questions

  Five derived endpoints, all computed from the snapshots SmartlyQ already collects - fast, unbilled, `analytics:read`:

  * **Daily metrics** - `GET /analytics/daily-metrics`: per-day aggregates + platform breakdown + posts published.
  * **Best time to post** - `GET /analytics/best-time?timezone=...`: 7x24 engagement heatmap and your top 5 slots.
  * **Post timeline** - `GET /analytics/posts/{post_id}/timeline`: every metric snapshot for one post, per platform.
  * **Content decay** - `GET /analytics/content-decay`: average share of final engagement by post age (day 0-13).
  * **Posting frequency** - `GET /analytics/posting-frequency`: weekly post count vs average engagement.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Account groups and profile moves

  * **Account groups** - full CRUD under `/social/account-groups`: name a set of connected accounts (a client, a brand) and address it with one id. Up to 50 groups per workspace, 100 accounts per group; membership is validated against your workspace on every write.
  * **Move to profile** - `POST /social/accounts/{account_id}/move` relocates a connected account between your developer workspace and your profiles (`profile_id: 0` moves it back). Requires `social:write` + `profiles:manage`, developer context only, and refuses with 409 while the account has scheduled or in-flight posts.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Account insights

  * **Bulk health** - `GET /social/accounts/health` reports every connected account's token health in one call: healthy / expiring / expired / paused tallies plus per-account detail. No more N+1 health polling.
  * **Follower stats** - `GET /social/accounts/follower-stats?days=30` returns daily follower history, growth, and growth percentage per account from the platform's analytics snapshots.
  * **Rename** - `PATCH /social/accounts/{account_id}` updates the account's display name.
  * **TikTok creator info** - `GET /social/accounts/{account_id}/tiktok/creator-info` surfaces live privacy levels, comment/duet/stitch availability, and max video duration - the fields TikTok requires you to show before posting.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Bulk scheduling and duplicate protection

  * **Bulk schedule** - `POST /social/posts/bulk` schedules up to 50 posts in one call, from a JSON `posts` array or an inline `csv` string (header: content, platforms, account\_ids, scheduled\_time, media\_urls, link). Billed one post unit per row x platform. A structural problem in any row rejects the whole batch with 422 before anything is created - and the charge is refunded.
  * **Free batch dry-run** - `POST /social/posts/bulk/validate` returns a per-row report (structure, per-platform caption/media limits, duplicate check) without creating or billing anything.
  * **24h duplicate-content guard** - `POST /social/posts` and `POST /social/posts/schedule` now reject content identical to a post created in the same workspace within the last 24 hours with `409 DUPLICATE_CONTENT` (charge refunded). Pass `allow_duplicates: true` to override. This catches retry loops and mis-wired crons before they spam your channels.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Evergreen post recycling

  Keep your best content in rotation automatically.

  * **Recycle on schedule** - `POST /social/posts/schedule` now accepts an optional `recycle` object: `{ interval_hours, max_repeats?, until? }`. After each occurrence publishes, the next one is scheduled automatically. A bound is required (`max_repeats` up to 100 and/or `until` up to 2 years out) - no unbounded chains.
  * **Stop a chain** - `DELETE /social/posts/{post_id}/recycle` clears the config across the whole chain and cancels any not-yet-published occurrences back to draft. Works from any post in the chain.
  * Occurrences inherit content, media, accounts, UTM tags, and approval status; `GET /social/posts/{post_id}` shows `recycle_count` and `recycle_parent_id` for lineage.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Pre-flight validation

  Catch problems before they cost a publish attempt. Both endpoints are free, unbilled, and need only `social:read`.

  * **Validate a post** - `POST /social/validate/post` dry-runs the exact checks the create path uses and returns a per-platform report: character count vs. the platform's caption limit, required-media rules, and media extension screening. Nothing is created.
  * **Validate a media URL** - `POST /social/validate/media` confirms a URL is publicly reachable and reports its content type, byte size, and detected kind (image/video). Private and internal hosts are rejected.

  See the [Validation reference](/api-reference) for the full report shape.
</Update>

<Update label="July 26, 2026" tags={["Social", "New"]}>
  ## Posting queues and unpublish

  Two of the most-requested scheduling powers land in the API.

  **Posting queues** - define a recurring weekly slot schedule once, then drop posts into it without computing times:

  * `GET/POST /social/queues`, `GET/PUT/DELETE /social/queues/{queue_id}` - manage queues (slot map `{"Mon": ["09:00"], ...}` + IANA timezone)
  * `GET /social/queues/{queue_id}/next-slot` and `/preview?count=N` - see upcoming open slots
  * `POST /social/posts/schedule` now takes `queue_id` instead of `scheduled_time`: the next open slot is resolved server-side and the post occupies it (FIFO), so concurrent calls fill consecutive slots
  * Bonus: `scheduled_time` now honors an optional `timezone` field (previously UTC-only)

  **Unpublish** - `POST /social/posts/{post_id}/unpublish` deletes a published post from its native platforms while keeping the record (status becomes `unpublished`). Optional `platforms` array restricts targets; per-platform results are returned, and if any native delete fails nothing changes so you can retry. Supported: Threads, Facebook, LinkedIn, YouTube, X, Pinterest, Tumblr, Bluesky, Google Business.
</Update>

<Update label="July 26, 2026" tags={["Webhooks", "New"]}>
  ## Webhooks: update, test, and delivery logs via API

  Webhook endpoints can now be fully managed and debugged without opening the dashboard.

  * `PUT /webhooks/{id}` - change the URL or subscribed events, or pause/resume deliveries (`status: active | paused`); re-activating also recovers an endpoint auto-paused after repeated failures
  * `POST /webhooks/{id}/test` - sends a `webhook.test` event through the real signing pipeline and returns the result synchronously (`delivered`, `response_code`, response excerpt)
  * `GET /webhooks/logs` - paginated delivery log across your endpoints with the full envelope, response code/body excerpt, attempt count, and next retry time; filter by `webhook_id`, `event`, or `status`
  * `job.completed` / `job.failed` now actually fire - these events were in the catalog but had no emit point; every async job now emits exactly once on its terminal transition with `{job_id, type, status, error?}`
  * Stricter validation: `POST /webhooks` and `PUT /webhooks/{id}` reject unknown event names outright instead of silently dropping them
  * Guardrail: webhook routes reject the `X-Profile-Id` header - webhooks live on your developer workspace and receive profile events via fan-up
</Update>

<Update label="July 26, 2026" tags={["Webhooks", "Docs"]}>
  ## Webhooks: unified 25-event catalog with machine-readable schemas

  The webhook documentation is now a single source of truth, aligned with what the platform actually delivers.

  * The [Webhooks guide](/guides/webhooks) now documents the complete **25-event catalog** (posting, accounts, inbox, jobs, billing & keys, CRM) with the `data` fields each event carries
  * Every event now ships a **JSON payload schema** in the OpenAPI spec's standard `webhooks` object - SDK generators and AI agents can consume delivery shapes directly from [openapi.json](https://docs.smartlyq.com/openapi.json)
  * `POST /webhooks` now documents the exact allowed `events` values (enum) instead of a free-form string array
  * Corrected legacy event names that appeared in older docs (`social.posted` → `post.published`, `wallet.low` → `balance.low`); the delivery envelope is documented as `{id, event, created_at, data}` with the `X-SmartlyQ-Event-Id` dedupe header
  * Documented previously-missing delivery semantics: `Retry-After` honored on 429 (capped 1h), dead-letter after the 5th attempt, auto-pause after 10 consecutive failures, 90-day delivery retention, 10 webhooks per workspace
</Update>

<Update label="July 25, 2026" tags={["Profiles", "New"]}>
  ## Profiles: build your own multi-tenant product

  Profiles turn the SmartlyQ API into infrastructure for YOUR product: create a profile per end-customer, let them self-connect their social accounts through a single-use hosted link (no SmartlyQ login), and operate the whole API inside their profile with one header.

  * `POST /profiles`, `GET /profiles`, `GET /profiles/{id}`, `GET /profiles/{id}/accounts`, pause / resume / delete
  * `POST /profiles/{id}/connect-link` - hosted, single-use connect page for your customer
  * `POST /profiles/{id}/connect/{platform}` - raw per-platform OAuth URLs for your own UI
  * `X-Profile-Id` header on existing endpoints - data scopes to the profile; billing, rate limits and logs stay on your account
  * `GET /me/account-billing` - live billable-account count and charge estimate
  * Per-account monthly billing from your API wallet: \$6 each for accounts 1-10, \$3 for 11-100, \$1 from 101 up
  * New webhook events `account_billing.charged` / `account_billing.failed`, plus every in-profile event now fans up to your webhooks with `profile_id` attached
  * New scopes: `profiles:read`, `profiles:write`, `profiles:manage`

  See the [Profiles guide](/guides/profiles).
</Update>

<Update label="July 22, 2026" tags={["Social"]}>
  ## More platform targets + pre-publish validation

  `POST /social/posts` and `POST /social/posts/schedule` now accept **10 platform targets**, adding Google Business, Threads, Bluesky, and Tumblr to the existing set. Every post now runs per-platform pre-publish validation (media formats, caption length, platform constraints), so invalid posts fail fast with an actionable `ValidationError` instead of failing at publish time.
</Update>

<Update label="July 16, 2026" tags={["Workspaces", "SaaS"]}>
  ## SaaS plan reads + bulk sub-account actions

  Agency and SaaS builders can now read their billing configuration and act on many sub-accounts at once:

  * `GET /saas/plans` and `GET /saas/plans/{id}` - list the SaaS plans configured on your account
  * `GET /workspaces/{id}/subscription` - a workspace's current plan and status
  * `GET /workspaces/{id}/wallet` - a workspace's credit wallet balance
  * `POST /workspaces/bulk` - pause, resume, or delete many workspaces in one call (SaaS-plan gated)

  See the new [Agency sub-accounts & SaaS guide](/guides/agency-saas).
</Update>

<Update label="July 15, 2026" tags={["Workspaces"]}>
  ## Workspace lifecycle management

  Full workspace (sub-account) lifecycle on the public API:

  * `POST /workspaces` - provision a new sub-account
  * `GET /workspaces` and `GET /workspaces/{id}` - list and inspect
  * `POST /workspaces/{id}/pause` and `/resume` - suspend and restore access
  * `POST /workspaces/{id}/disable-saas` - detach a workspace from your SaaS plan
  * `DELETE /workspaces/{id}` - guarded delete with async teardown
</Update>

<Update label="July 15, 2026" tags={["CRM"]}>
  ## CRM API: contacts, opportunities, custom fields

  The CRM is now fully scriptable:

  * Contacts: create, list, get, update, tag management, notes, `POST /contacts/{id}/enroll` (enroll in an automation), and `POST /contacts/{id}/messages` (log a message to the timeline)
  * Custom fields: `GET`/`POST /custom-fields`, `DELETE /custom-fields/{id}`
  * Pipelines and opportunities: full CRUD plus `POST /opportunities/{id}/status` for stage moves
  * Outbound CRM events are delivered through your existing [webhooks](/guides/webhooks)

  All CRM endpoints are also exposed as MCP tools.
</Update>

<Update label="July 14, 2026" tags={["Presentations"]}>
  ## Presentations API

  Generate full AI slide decks from a single prompt:

  * `POST /presentations/generate` - builds a complete deck (3 to 12 slides, language and tone options) and returns the presentation id plus edit and share URLs
  * `GET /presentations`, `GET /presentations/{id}`, `DELETE /presentations/{id}`

  New scopes: `presentations:write` and `presentations:read`.
</Update>

<Update label="July 7, 2026" tags={["SEO"]}>
  ## Async SEO lookups

  Long-running SEO operations (`/seo/site-audit`, `/seo/rank-history`, `/seo/brand-lookup`, `/seo/prompt-explorer`, `/seo/ai-audit`) now return `202 Accepted` with a job id instead of holding the connection open. Poll `GET /jobs/{job_id}` for the result. Hot reads are cached, so repeated lookups on the same target return faster.
</Update>

<Update label="July 6, 2026" tags={["SEO", "New"]}>
  ## AI visibility endpoints

  Three new SEO endpoints for the AI-search era:

  * `POST /seo/ai-audit` - audit how visible a domain is to AI assistants; also delivers a PDF report by email
  * `POST /seo/brand-lookup` - how a brand appears across search and AI surfaces
  * `POST /seo/prompt-explorer` - discover the prompts where a domain is (or is not) cited
</Update>

<Update label="July 5, 2026" tags={["Videos", "Shorts"]}>
  ## Shorts + video editing AI

  Turn long videos into ranked short clips, and use the editor's AI helpers directly:

  * `POST /shorts/generate` - split a long video (or a source URL) into ranked viral clips; poll `GET /shorts/{uid}`
  * `POST /videos/hook` - a scroll-stopping overlay line for a video
  * `POST /videos/broll-suggest` and `POST /videos/emphasis` - B-roll and emphasis suggestions from a word-level transcript
  * `POST /videos/viral-thumbnail` - generate a thumbnail from a title
  * `POST /content/caption` - platform-tuned social captions
</Update>

<Update label="July 4, 2026" tags={["Developer Portal"]}>
  ## Logs overhaul

  The Developer Portal's Logs tab is now a unified request feed with endpoint, status, and platform filters, plus CSV export. Sanitized request payloads are captured for easier debugging.
</Update>

<Update label="July 3, 2026" tags={["Billing"]}>
  ## Billing correctness hardening

  Wallet charges are now fully idempotent (safe retries with `Idempotency-Key` can never double-charge), refunds are serialized against the wallet row, and priced units fail closed. Billed requests that end in a `4xx`/`5xx` are automatically refunded to the original credit buckets.
</Update>

<Update label="June 28, 2026" tags={["Webhooks"]}>
  ## Webhooks: unified event catalog + signed envelope

  Webhooks are now generally available with a unified 13-event catalog:

  `post.published` / `post.failed` / `post.partial`, `account.connected` / `account.disconnected` / `account.token_expired`, `comment.received`, `message.received`, `job.completed` / `job.failed`, `balance.low`, `balance.depleted`, `key.revoked`

  Every delivery carries a canonical envelope `{ id, event, created_at, data }` with headers `X-SmartlyQ-Event` and `X-SmartlyQ-Event-Id` (stable across retries), signed with `X-SmartlyQ-Signature` (HMAC-SHA256, timestamped). Deliveries retry 5 times with exponential backoff before dead-lettering. See the [Webhooks guide](/guides/webhooks).
</Update>

<Update label="June 27, 2026" tags={["SEO", "New"]}>
  ## SEO API launch

  14 SEO endpoints under `/seo/*` with the new `seo:read` scope: keyword research, SERP analysis, keyword difficulty, ranked keywords, domain overview, competitors, backlinks summary, backlink prospects, referring domains, backlink anchors, spam score, rank history, site audit, and on-page audit.
</Update>

<Update label="June 8, 2026" tags={["Developer Portal", "Billing"]}>
  ## Playground + automatic refunds

  * The in-app **API Playground** can now run real requests against any of your keys (scopes, billing, and rate limits all apply; write calls need explicit confirmation)
  * Charges are taken upfront and **automatically refunded** if the request fails
  * Wallet ledger rows now carry human-readable descriptions
</Update>

<Update label="June 6, 2026" tags={["Social", "Webhooks", "New"]}>
  ## Headless connect for all 13 platforms

  End-to-end account connection without the SmartlyQ UI:

  * `GET /social/connect/{platform}` - start a headless OAuth connect for any of the 13 platforms and poll connection status
  * `GET`/`POST /webhooks` and `DELETE /webhooks/{id}` - manage webhook subscriptions from the API, including a deliveries index and dead-letter view
  * Post results now surface **per-platform publish failure reasons**
  * Error envelope extended with `retryable`, `fix`, and `docs_url` fields
  * Platform posting rate limits are enforced at create time with clear errors
</Update>

<Update label="June 5, 2026" tags={["Social", "New"]}>
  ## Comments, DMs, and account lifecycle

  The social engagement surface arrives on `/v1`:

  * Comments: `GET /social/comments`, `POST .../reply`, `POST .../hide`, `DELETE /social/comments/{id}`
  * Inbox: `GET /social/conversations`, `GET`/`POST .../messages`, `POST .../read`
  * Accounts: `GET .../health`, `GET .../reconnect-url`, `POST .../pause`, `POST .../resume`, `DELETE /social/accounts/{id}`
  * `POST /social/posts/{post_id}/retry` - retry only the platforms that failed

  All list responses use the standard `data` + `pagination` envelope.
</Update>
